How to update listView using MVVM pattern and ObservableCollection in WPF?

Imilio 41 Reputation points
2022-01-11T20:39:56.773+00:00

I want to update a listview in UserControl included in MainWindow when adding/removing an entry over opening a Window.
When clicking the save button, nothing happens
Can anyone please help me to see, what I'm doing wrong?

Best regards
Imilio

What I have done:

XAML - MainWindow

<Window x:Class="Add_Edit_Delete.ucWindow.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:Add_Edit_Delete.ucWindow" xmlns:local1="clr-namespace:Add_Edit_Delete.ViewModel"
        mc:Ignorable="d"
        Title="Window1" Height="450" Width="400">

    <Window.DataContext>
        <local1:AddViewModel/>
    </Window.DataContext>

    <Grid>
        <StackPanel>

            <StackPanel Orientation="Horizontal" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="0,0,0,10">
                <Label Content="Firstname:" Width="120" />
                <TextBox x:Name="tbFirstname" Height="25" Width="230" Margin="0,0,5,0" Text="{Binding NewUser.Firstname}"/>
            </StackPanel>

            <StackPanel Orientation="Horizontal" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="0,0,0,10">
                <Label Content="Firstname:" Width="120" />
                <TextBox x:Name="tbLastname" Height="25" Width="230" Margin="0,0,5,0" Text="{Binding NewUser.Lastname}"/>
            </StackPanel>



        </StackPanel>

        <StackPanel Orientation="Horizontal" VerticalAlignment="Bottom" HorizontalAlignment="Right" Margin="10,0,10,10">
            <Button Height="30" Width="70" Content="Close" Margin="10,0,0,0"/>
            <Button Height="30" Width="70" Content="Save" Margin="10,0,0,0" Command="{Binding AddUserCommand}"/>
        </StackPanel>
    </Grid>
</Window>

C# - MainWindow

using Add_Edit_Delete.Usercontrol;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace Add_Edit_Delete
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void User_Click(object sender, RoutedEventArgs e)
        {
            UserControl1 oUser = new UserControl1();
            Grid.SetColumn(oUser, 1);
            MainGrid.Children.Add(oUser);
        }
    }
}

XAML - UserControl1

<UserControl x:Class="Add_Edit_Delete.Usercontrol.UserControl1"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:Add_Edit_Delete.Usercontrol" xmlns:local1="clr-namespace:Add_Edit_Delete.ViewModel"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800" Background="White">

    <UserControl.DataContext>
        <local1:UserViewModel/>
    </UserControl.DataContext>

    <Grid>

        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>

        <ListView Grid.Column="0">
            <ListView.View>
                <GridView>
                    <GridViewColumn Header="Firstname" x:Name="Firstname" Width="200">
                        <GridViewColumn.CellTemplate>
                            <DataTemplate>
                                <TextBlock Text="{Binding Firstname}" TextWrapping="Wrap"/>
                            </DataTemplate>
                        </GridViewColumn.CellTemplate>
                    </GridViewColumn>
                    <GridViewColumn Header="Lastname" x:Name="Lastname" Width="200">
                        <GridViewColumn.CellTemplate>
                            <DataTemplate>
                                <TextBlock Text="{Binding Lastname}" TextWrapping="Wrap"/>
                            </DataTemplate>
                        </GridViewColumn.CellTemplate>
                    </GridViewColumn>
                </GridView>
            </ListView.View>
        </ListView>


        <StackPanel Grid.Column="1" Orientation="Horizontal" VerticalAlignment="Top" Margin="20,0,0,0">

            <Button Height="25" Width="50" Content="Add" Margin="10" Click="Add_Click"/>
            <Button Height="25" Width="50" Content="Edit" Margin="10" Click="Eddit_Click"/>
            <Button Height="25" Width="50" Content="Delete" Margin="10" Click="Delete_Click" /> 

        </StackPanel>

    </Grid>
</UserControl>

C# - UserControl1

    using Add_Edit_Delete.ucWindow;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;

    namespace Add_Edit_Delete.Usercontrol
    {
        /// <summary>
        /// Interaktionslogik für UserControl1.xaml
        /// </summary>
        public partial class UserControl1 : UserControl
        {
            public UserControl1()
            {
                InitializeComponent();
            }


            private void Delete_Click(object sender, RoutedEventArgs e)
            {

            }

            private void Eddit_Click(object sender, RoutedEventArgs e)
            {

            }

            private void Add_Click(object sender, RoutedEventArgs e)
            {
                Window1 oAdd = new Window1();
                oAdd.Owner = Application.Current.MainWindow;
                oAdd.ShowDialog();
            }
        }
    }


**XAML - Window1**


<Window x:Class="Add_Edit_Delete.ucWindow.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:Add_Edit_Delete.ucWindow" xmlns:local1="clr-namespace:Add_Edit_Delete.ViewModel"
        mc:Ignorable="d"
        Title="Window1" Height="450" Width="400">

    <Window.DataContext>
        <local1:AddViewModel/>
    </Window.DataContext>

    <Grid>
        <StackPanel>

            <StackPanel Orientation="Horizontal" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="0,0,0,10">
                <Label Content="Firstname:" Width="120" />
                <TextBox x:Name="tbFirstname" Height="25" Width="230" Margin="0,0,5,0" Text="{Binding NewUser.Firstname}"/>
            </StackPanel>

            <StackPanel Orientation="Horizontal" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="0,0,0,10">
                <Label Content="Firstname:" Width="120" />
                <TextBox x:Name="tbLastname" Height="25" Width="230" Margin="0,0,5,0" Text="{Binding NewUser.Lastname}"/>
            </StackPanel>



        </StackPanel>

        <StackPanel Orientation="Horizontal" VerticalAlignment="Bottom" HorizontalAlignment="Right" Margin="10,0,10,10">
            <Button Height="30" Width="70" Content="Close" Margin="10,0,0,0"/>
            <Button Height="30" Width="70" Content="Save" Margin="10,0,0,0" Command="{Binding AddUserCommand}"/>
        </StackPanel>
    </Grid>
</Window>

C# - Window1

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

namespace Add_Edit_Delete.ucWindow
{
    /// <summary>
    /// Interaktionslogik für Window1.xaml
    /// </summary>
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
        }
    }
}

UserModel

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Add_Edit_Delete.Model
{
    class UserModel
    {
        public int Id { get; set; }
        public string Firstname { get; set; }
        public string Lastname { get; set; }
    }
}

AddViewModel

using Add_Edit_Delete.Commands;
using Add_Edit_Delete.Model;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Add_Edit_Delete.ViewModel
{
    class AddViewModel : INotifyPropertyChanged
    {
        public AddViewModel()
        {
            this.AddUserCommand = new DelegateCommand((o) =>
            {
                this.ListOfUser.Add(NewUser);
            });
        }

        UserModel newUser = new UserModel();
        public UserModel NewUser
        {
            get => newUser;
            set
            {
                if (newUser != value)
                {
                    newUser = value;
                    this.RaisePropertyChanged(nameof(NewUser));
                }
            }
        }

        private ObservableCollection<UserModel> listOfUser = new ObservableCollection<UserModel>();
        public ObservableCollection<UserModel> ListOfUser
        {
            get => listOfUser;
            set
            {
                if (listOfUser != value)
                {
                    listOfUser = value;
                    this.RaisePropertyChanged(nameof(ListOfUser));
                }
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private void RaisePropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        public DelegateCommand AddUserCommand { get; set; }
    }
}

UserViewModel

using Add_Edit_Delete.Model;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Add_Edit_Delete.ViewModel 
{
    class UserViewModel : INotifyPropertyChanged
    {
        UserModel newUser = new UserModel();
        public UserModel NewUser
        {
            get => newUser;
            set
            {
                if (newUser != value)
                {
                    newUser = value;
                    this.RaisePropertyChanged(nameof(NewUser));
                }
            }
        }

        private ObservableCollection<UserModel> listOfUser = new ObservableCollection<UserModel>();
        public ObservableCollection<UserModel> ListOfUser
        {
            get => listOfUser;
            set
            {
                if (listOfUser != value)
                {
                    listOfUser = value;
                    this.RaisePropertyChanged(nameof(ListOfUser));
                }
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private void RaisePropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
}

DelegationCommand

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;

namespace Add_Edit_Delete.Commands
{
    public class DelegateCommand : ICommand
    {


        readonly Action<object> execute;

        readonly Predicate<object> canExecute;

        public DelegateCommand(Predicate<object> canExecute, Action<object> execute) =>
            (this.canExecute, this.execute) = (canExecute, execute);

        public DelegateCommand(Action<object> execute) : this(null, execute) { }


        public event EventHandler CanExecuteChanged;


        public void RaiseCanExecuteChanged() => this.CanExecuteChanged?.Invoke(this, EventArgs.Empty);


        public bool CanExecute(object parameter) => this.canExecute?.Invoke(parameter) ?? true; 

        public void Execute(object parameter) => this.execute?.Invoke(parameter);
    }
}

The project can be downloaded here

Developer technologies | Windows Presentation Foundation
0 comments No comments
{count} votes

10 answers

Sort by: Most helpful
  1. Imilio 41 Reputation points
    2022-01-17T19:18:03.413+00:00

    Hi @Peter Fleischer (former MVP) , your code works great. I have been trying to implement new things lately. But with MVVM it is very time consuming for me. So now I want to program with code behind. But the simplest example (updating ListView) did not work. Is there something I don't understand correctly?

    UserControl1

    using System;  
    using System.Collections.Generic;  
    using System.Linq;  
    using System.Text;  
    using System.Threading.Tasks;  
    using System.Windows;  
    using System.Windows.Controls;  
    using System.Windows.Data;  
    using System.Windows.Documents;  
    using System.Windows.Input;  
    using System.Windows.Media;  
    using System.Windows.Media.Imaging;  
    using System.Windows.Navigation;  
    using System.Windows.Shapes;  
    using WPF_App.ucWindow;  
    using WPF_App.ViewModel;  
      
    namespace WPF_App.Usercontrol  
    {  
        /// <summary>  
        /// Interaktionslogik für UserControl1.xaml  
        /// </summary>  
        public partial class UserControl1 : UserControl  
        {  
            public UserControl1()  
            {  
                InitializeComponent();  
            }  
      
            private void Add_Click(object sender, RoutedEventArgs e)  
            {  
                Window1 oAdd = new Window1();  
                oAdd.Owner = Application.Current.MainWindow;  
                oAdd.ShowDialog();  
      
            }  
        }  
    }  
    

    XAML

    <UserControl x:Class="WPF_App.Usercontrol.UserControl1"  
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
                 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"   
                 xmlns:d="http://schemas.microsoft.com/expression/blend/2008"   
                 xmlns:local="clr-namespace:WPF_App.Usercontrol" xmlns:local1="clr-namespace:WPF_App.ViewModel"  
                 mc:Ignorable="d"   
                 d:DesignHeight="450" d:DesignWidth="800" Background="White">  
      
        <UserControl.DataContext>  
            <local1:UserViewModel/>  
        </UserControl.DataContext>  
      
        <Grid>  
            <Grid.ColumnDefinitions>  
                <ColumnDefinition Width="*"/>  
                <ColumnDefinition Width="*"/>  
            </Grid.ColumnDefinitions>  
      
            <ListView Grid.Column="0" ItemsSource="{Binding ListOfUser}">  
                <ListView.View>  
                    <GridView>  
                        <GridViewColumn Header="Firstname" x:Name="Firstname" Width="200">  
                            <GridViewColumn.CellTemplate>  
                                <DataTemplate>  
                                    <TextBlock Text="{Binding Firstname}" TextWrapping="Wrap"/>  
                                </DataTemplate>  
                            </GridViewColumn.CellTemplate>  
                        </GridViewColumn>  
                        <GridViewColumn Header="Lastname" x:Name="Lastname" Width="200">  
                            <GridViewColumn.CellTemplate>  
                                <DataTemplate>  
                                    <TextBlock Text="{Binding Lastname}" TextWrapping="Wrap"/>  
                                </DataTemplate>  
                            </GridViewColumn.CellTemplate>  
                        </GridViewColumn>  
                    </GridView>  
                </ListView.View>  
            </ListView>  
      
            <StackPanel Grid.Column="1" Orientation="Horizontal" VerticalAlignment="Top" Margin="20,0,0,0">  
      
                <Button Height="25" Width="50" Content="Add" Margin="10" Click="Add_Click"  />  
                <Button Height="25" Width="50" Content="Edit" Margin="10" />  
                <Button Height="25" Width="50" Content="Delete" Margin="10"/>  
      
            </StackPanel>  
              
        </Grid>  
    </UserControl>  
    

    UserViewModel

    using System;  
    using System.Collections.Generic;  
    using System.Collections.ObjectModel;  
    using System.ComponentModel;  
    using System.Linq;  
    using System.Text;  
    using System.Threading.Tasks;  
    using System.Windows;  
    using System.Windows.Input;  
    using WPF_App.Commands;  
    using WPF_App.Model;  
    using WPF_App.ucWindow;  
      
    namespace WPF_App.ViewModel  
    {  
        public class UserViewModel : INotifyPropertyChanged  
        {  
            public void SaveUsers()  
            {  
                this.ListOfUser.Add(NewUser.Copy());  
                RaisePropertyChanged(nameof(SaveUsers));  
            }  
      
      
            public UserModel NewUser { get; set; } = new UserModel();  
      
            public ObservableCollection<UserModel> ListOfUser { get; set; } = new ObservableCollection<UserModel>();  
      
            public event PropertyChangedEventHandler PropertyChanged;  
            private void RaisePropertyChanged(string propertyName) =>  
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));  
        }  
    }  
    

    Window1

    using System;  
    using System.Collections.Generic;  
    using System.Linq;  
    using System.Text;  
    using System.Threading.Tasks;  
    using System.Windows;  
    using System.Windows.Controls;  
    using System.Windows.Data;  
    using System.Windows.Documents;  
    using System.Windows.Input;  
    using System.Windows.Media;  
    using System.Windows.Media.Imaging;  
    using System.Windows.Shapes;  
    using WPF_App.ViewModel;  
      
    namespace WPF_App.ucWindow  
    {  
        /// <summary>  
        /// Interaktionslogik für Window1.xaml  
        /// </summary>  
        public partial class Window1 : Window  
        {  
            public Window1()  
            {  
                InitializeComponent();  
            }  
      
            private void Save_Click(object sender, RoutedEventArgs e)  
            {  
                UserViewModel UserVM = new UserViewModel();  
                UserVM.SaveUsers();  
            }  
      
            private void Close_Click(object sender, RoutedEventArgs e)  
            {  
      
            }  
        }  
    }  
    

  2. Imilio 41 Reputation points
    2022-01-17T22:07:54.933+00:00

    Hi @Peter Fleischer (former MVP) , I post the whole code from the app.

    MainWindow.xaml:

    <Window x:Class="WPF_App.MainWindow"  
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"  
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"  
            xmlns:local="clr-namespace:WPF_App"  
            mc:Ignorable="d"  
            Title="MainWindow" Height="450" Width="800">  
        <Grid x:Name="MainGrid">  
              
            <Grid.ColumnDefinitions>  
                <ColumnDefinition Width="70"/>  
                <ColumnDefinition Width="*"/>  
            </Grid.ColumnDefinitions>  
      
            <StackPanel Grid.Column="0" Orientation="Vertical" VerticalAlignment="Top" >  
                <Button Height="50" Width="50" Content="User" Margin="10" Click="User_Click"  />  
                <Button Height="50" Width="50" Content="Pub" Margin="10"/>  
            </StackPanel>  
              
        </Grid>  
    </Window>  
    

    MainWindow.xaml.cs

    using System;  
    using System.Collections.Generic;  
    using System.Linq;  
    using System.Text;  
    using System.Threading.Tasks;  
    using System.Windows;  
    using System.Windows.Controls;  
    using System.Windows.Data;  
    using System.Windows.Documents;  
    using System.Windows.Input;  
    using System.Windows.Media;  
    using System.Windows.Media.Imaging;  
    using System.Windows.Navigation;  
    using System.Windows.Shapes;  
    using WPF_App.Usercontrol;  
      
    namespace WPF_App  
    {  
        /// <summary>  
        /// Interaction logic for MainWindow.xaml  
        /// </summary>  
        public partial class MainWindow : Window  
        {  
            public MainWindow()  
            {  
                InitializeComponent();  
            }  
      
            private void User_Click(object sender, RoutedEventArgs e)  
            {  
                UserControl1 oUser = new UserControl1();  
                Grid.SetColumn(oUser, 1);  
                MainGrid.Children.Add(oUser);  
            }  
        }  
    }  
    

    UserControl1.xaml:

    <UserControl x:Class="WPF_App.Usercontrol.UserControl1"  
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
                 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"   
                 xmlns:d="http://schemas.microsoft.com/expression/blend/2008"   
                 xmlns:local="clr-namespace:WPF_App.Usercontrol" xmlns:local1="clr-namespace:WPF_App.ViewModel"  
                 mc:Ignorable="d"   
                 d:DesignHeight="450" d:DesignWidth="800" Background="White">  
      
        <UserControl.DataContext>  
            <local1:UserViewModel/>  
        </UserControl.DataContext>  
      
        <Grid>  
            <Grid.ColumnDefinitions>  
                <ColumnDefinition Width="*"/>  
                <ColumnDefinition Width="*"/>  
            </Grid.ColumnDefinitions>  
      
            <ListView Grid.Column="0" ItemsSource="{Binding ListOfUser}">  
                <ListView.View>  
                    <GridView>  
                        <GridViewColumn Header="Firstname" x:Name="Firstname" Width="200">  
                            <GridViewColumn.CellTemplate>  
                                <DataTemplate>  
                                    <TextBlock Text="{Binding Firstname}" TextWrapping="Wrap"/>  
                                </DataTemplate>  
                            </GridViewColumn.CellTemplate>  
                        </GridViewColumn>  
                        <GridViewColumn Header="Lastname" x:Name="Lastname" Width="200">  
                            <GridViewColumn.CellTemplate>  
                                <DataTemplate>  
                                    <TextBlock Text="{Binding Lastname}" TextWrapping="Wrap"/>  
                                </DataTemplate>  
                            </GridViewColumn.CellTemplate>  
                        </GridViewColumn>  
                    </GridView>  
                </ListView.View>  
            </ListView>  
      
            <StackPanel Grid.Column="1" Orientation="Horizontal" VerticalAlignment="Top" Margin="20,0,0,0">  
      
                <Button Height="25" Width="50" Content="Add" Margin="10" Click="Add_Click"  />  
                <Button Height="25" Width="50" Content="Edit" Margin="10" />  
                <Button Height="25" Width="50" Content="Delete" Margin="10"/>  
      
            </StackPanel>  
              
        </Grid>  
    </UserControl>  
    

    UserControl1.xaml.cs:

    using System;  
    using System.Collections.Generic;  
    using System.Linq;  
    using System.Text;  
    using System.Threading.Tasks;  
    using System.Windows;  
    using System.Windows.Controls;  
    using System.Windows.Data;  
    using System.Windows.Documents;  
    using System.Windows.Input;  
    using System.Windows.Media;  
    using System.Windows.Media.Imaging;  
    using System.Windows.Navigation;  
    using System.Windows.Shapes;  
    using WPF_App.ucWindow;  
    using WPF_App.ViewModel;  
      
    namespace WPF_App.Usercontrol  
    {  
        /// <summary>  
        /// Interaktionslogik für UserControl1.xaml  
        /// </summary>  
        public partial class UserControl1 : UserControl  
        {  
            public UserControl1()  
            {  
                InitializeComponent();  
            }  
      
            private void Add_Click(object sender, RoutedEventArgs e)  
            {  
                Window1 oAdd = new Window1();  
                oAdd.Owner = Application.Current.MainWindow;  
                oAdd.ShowDialog();  
      
            }  
        }  
    }  
    

    Window1.xaml:

    <Window x:Class="WPF_App.ucWindow.Window1"  
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"  
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"  
            xmlns:local="clr-namespace:WPF_App.ucWindow"   
            mc:Ignorable="d"  
            Title="Window1" Height="450" Width="400">  
      
        <Grid>  
              
            <StackPanel>  
      
                <StackPanel Orientation="Horizontal" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="0,0,0,10">  
                    <Label Content="Firstname:" Width="120" />  
                    <TextBox x:Name="tbFirstname" Height="25" Width="230" Margin="0,0,5,0" Text="{Binding NewUser.Firstname}"/>  
                </StackPanel>  
      
                <StackPanel Orientation="Horizontal" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="0,0,0,10">  
                    <Label Content="Firstname:" Width="120" />  
                    <TextBox x:Name="tbLastname" Height="25" Width="230" Margin="0,0,5,0" Text="{Binding NewUser.Lastname}"/>  
                </StackPanel>  
      
            </StackPanel>  
      
            <StackPanel Orientation="Horizontal" VerticalAlignment="Bottom" HorizontalAlignment="Right" Margin="10,0,10,10">  
                <Button Height="30" Width="70" Content="Close" Margin="10,0,0,0" Click="Close_Click"/>  
                <Button Height="30" Width="70" Content="Save" Margin="10,0,0,0" Click="Save_Click" />  
            </StackPanel>  
      
        </Grid>  
    </Window>  
    

    Window1.xaml.cs

    using System;  
    using System.Collections.Generic;  
    using System.Linq;  
    using System.Text;  
    using System.Threading.Tasks;  
    using System.Windows;  
    using System.Windows.Controls;  
    using System.Windows.Data;  
    using System.Windows.Documents;  
    using System.Windows.Input;  
    using System.Windows.Media;  
    using System.Windows.Media.Imaging;  
    using System.Windows.Shapes;  
    using WPF_App.ViewModel;  
      
    namespace WPF_App.ucWindow  
    {  
        /// <summary>  
        /// Interaktionslogik für Window1.xaml  
        /// </summary>  
        public partial class Window1 : Window  
        {  
            public Window1()  
            {  
                InitializeComponent();  
            }  
      
            private void Save_Click(object sender, RoutedEventArgs e)  
            {  
                UserViewModel UserVM = new UserViewModel();  
                UserVM.SaveUsers();  
            }  
      
            private void Close_Click(object sender, RoutedEventArgs e)  
            {  
      
            }  
        }  
    }  
    

    UserModel:

    using System;  
    using System.Collections.Generic;  
    using System.Linq;  
    using System.Text;  
    using System.Threading.Tasks;  
      
    namespace WPF_App.Model  
    {  
        public class UserModel  
        {  
            static int number = 1;  
            public int Id { get; set; }  
            public string Firstname { get; set; }  
            public string Lastname { get; set; }  
            public UserModel Copy() => new UserModel() { Id = number++, Firstname = this.Firstname, Lastname = this.Lastname };  
        }  
    }  
    

    UserControlViewModel:

    using System;  
    using System.Collections.Generic;  
    using System.Collections.ObjectModel;  
    using System.ComponentModel;  
    using System.Linq;  
    using System.Text;  
    using System.Threading.Tasks;  
    using System.Windows;  
    using System.Windows.Input;  
    using WPF_App.Commands;  
    using WPF_App.Model;  
    using WPF_App.ucWindow;  
      
    namespace WPF_App.ViewModel  
    {  
        public class UserViewModel : INotifyPropertyChanged  
        {  
            public void SaveUsers()  
            {  
                this.ListOfUser.Add(NewUser.Copy());  
                RaisePropertyChanged(nameof(SaveUsers));  
            }  
      
      
            public UserModel NewUser { get; set; } = new UserModel();  
      
            public ObservableCollection<UserModel> ListOfUser { get; set; } = new ObservableCollection<UserModel>();  
      
            public event PropertyChangedEventHandler PropertyChanged;  
            private void RaisePropertyChanged(string propertyName) =>  
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));  
        }  
    }  
    

    Window1 communicate with UserViewModel via"Text="{Binding NewUser.Firstname} and Text="{Binding NewUser.Lastname}", and UserControl1 communicate with UserViewModel1 with UserViewModel via instance UserVM or do I understand the whole thing wrong?


  3. Imilio 41 Reputation points
    2022-01-19T10:40:59.293+00:00

    It is very simple. I do not want to use commands. I want to work with code behind. Maybe you can help me to make my code work otherwise thanks for your help already done

    0 comments No comments

  4. Peter Fleischer (former MVP) 19,341 Reputation points
    2022-01-20T11:10:46.26+00:00

    Hi,
    I didn't unterstand why you cannot copy code from ViewModel to Codebehind.

    XAML UserControl:

    <UserControl x:Class="WpfControlLibrary1.Window094UC1"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
                 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
                 xmlns:local="clr-namespace:WpfControlLibrary1"
                 xmlns:local1="clr-namespace:WpfControlLibrary094.Add_Edit_Delete.ViewModel"
                 mc:Ignorable="d" 
                 d:DesignHeight="450" d:DesignWidth="800">
      <Grid>
        <Grid.ColumnDefinitions>
          <ColumnDefinition Width="*"/>
          <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <ListView Grid.Column="0" ItemsSource="{Binding ListOfUser}">
          <ListView.View>
            <GridView>
              <GridViewColumn Header="Firstname" x:Name="Firstname" Width="200">
                <GridViewColumn.CellTemplate>
                  <DataTemplate>
                    <TextBlock Text="{Binding Firstname}" TextWrapping="Wrap"/>
                  </DataTemplate>
                </GridViewColumn.CellTemplate>
              </GridViewColumn>
              <GridViewColumn Header="Lastname" x:Name="Lastname" Width="200">
                <GridViewColumn.CellTemplate>
                  <DataTemplate>
                    <TextBlock Text="{Binding Lastname}" TextWrapping="Wrap"/>
                  </DataTemplate>
                </GridViewColumn.CellTemplate>
              </GridViewColumn>
            </GridView>
          </ListView.View>
        </ListView>
        <StackPanel Grid.Column="1" Orientation="Horizontal" VerticalAlignment="Top" Margin="20,0,0,0">
          <Button Height="25" Width="50" Content="Add" Margin="10" Click="Add_Click"/>
          <Button Height="25" Width="50" Content="Edit" Margin="10" Click="Eddit_Click"/>
          <Button Height="25" Width="50" Content="Delete" Margin="10" Click="Delete_Click" />
        </StackPanel>
      </Grid>
    </UserControl>
    

    whole code:

    using System;
    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Input;
    using WpfControlLibrary094.Add_Edit_Delete.Commands;
    using WpfControlLibrary094.Add_Edit_Delete.ViewModel;
    using WpfControlLibrary1;
    
    namespace WpfControlLibrary1
    {
      /// <summary>
      /// Interaction logic for Window094UC1.xaml
      /// </summary>
      public partial class Window094UC1 : UserControl
      {
        public Window094UC1()
        {
          InitializeComponent();
          DataContext = _userViewModel;
        }
        UserViewModel _userViewModel = new UserViewModel();
        private void Add_Click(object sender, RoutedEventArgs e) => _userViewModel.CmdExec("Add_Click");
        private void Eddit_Click(object sender, RoutedEventArgs e) => _userViewModel.CmdExec("Eddit_Click");
        private void Delete_Click(object sender, RoutedEventArgs e) => _userViewModel.CmdExec("Delete_Click");
      }
    }
    
    namespace WpfControlLibrary094.Add_Edit_Delete.ViewModel
    {
      public class UserModel
      {
        public int Id { get; set; }
        public string Firstname { get; set; }
        public string Lastname { get; set; }
      }
    
      public class UserViewModel
      {
        public ObservableCollection<UserModel> ListOfUser { get; set; } = new ObservableCollection<UserModel>();
        internal void CmdExec(object obj)
        {
          switch (obj.ToString())
          {
            case "Add_Click":
              Window094A oAdd = new Window094A();
              AddViewModel vm = new AddViewModel(this);
              oAdd.DataContext = vm;
              oAdd.Owner = Application.Current.MainWindow;
              oAdd.ShowDialog();
              break;
            default:
              break;
          }
        }
      }
    
      public class AddViewModel : INotifyPropertyChanged
      {
        public AddViewModel(UserViewModel vm)
        {
          mainVm = vm;
          this.AddUserCommand = new DelegateCommand((o) =>
          {
            mainVm.ListOfUser.Add(NewUser);
            NewUser = new UserModel();
            RaisePropertyChanged(nameof(NewUser));
          });
        }
        public DelegateCommand AddUserCommand { get; set; }
    
        private UserViewModel mainVm;
    
        public UserModel NewUser { get; set; } = new UserModel();
    
        public event PropertyChangedEventHandler PropertyChanged;
        private void RaisePropertyChanged(string propertyName) =>
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
      }
    }
    
    namespace WpfControlLibrary094.Add_Edit_Delete.Commands
    {
      public class DelegateCommand : ICommand
      {
        readonly Action<object> execute;
        readonly Predicate<object> canExecute;
        public DelegateCommand(Predicate<object> canExecute, Action<object> execute) =>
          (this.canExecute, this.execute) = (canExecute, execute);
        public DelegateCommand(Action<object> execute) : this(null, execute) { }
        public event EventHandler CanExecuteChanged;
        public void RaiseCanExecuteChanged() => this.CanExecuteChanged?.Invoke(this, EventArgs.Empty);
        public bool CanExecute(object parameter) => this.canExecute?.Invoke(parameter) ?? true;
        public void Execute(object parameter) => this.execute?.Invoke(parameter);
      }
    }
    

  5. Peter Fleischer (former MVP) 19,341 Reputation points
    2022-01-21T20:50:09.277+00:00

    Hi,
    see the whole code without Commands:

    <Window x:Class="WpfApp1.Window094"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:WpfApp1"
            xmlns:local1="clr-namespace:WpfControlLibrary094.Add_Edit_Delete.ViewModel;assembly=WpfControlLibrary1"
            xmlns:uc="clr-namespace:WpfControlLibrary1;assembly=WpfControlLibrary1"
            mc:Ignorable="d"
            Title="Imilio-3053_220112" Height="450" Width="800">
      <Grid>
        <StackPanel>
          <uc:Window094UC1 Margin="5"/>
          <uc:Window094UC1 Margin="5"/>
          <uc:Window094UC1 Margin="5"/>
        </StackPanel>
      </Grid>
    </Window>
    

    <Window x:Class="WpfControlLibrary1.Window094A"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:WpfControlLibrary1"
            xmlns:local1="clr-namespace:WpfControlLibrary094.Add_Edit_Delete.ViewModel"
            mc:Ignorable="d"
            Title="Window1" Height="150" Width="400">
      <Grid>
        <StackPanel>
          <StackPanel Orientation="Horizontal" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="0,0,0,10">
            <Label Content="Firstname:" Width="120" />
            <TextBox x:Name="tbFirstname" Height="25" Width="230" Margin="0,0,5,0" Text="{Binding NewUser.Firstname}"/>
          </StackPanel>
          <StackPanel Orientation="Horizontal" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="0,0,0,10">
            <Label Content="Firstname:" Width="120" />
            <TextBox x:Name="tbLastname" Height="25" Width="230" Margin="0,0,5,0" Text="{Binding NewUser.Lastname}"/>
          </StackPanel>
        </StackPanel>
        <StackPanel Orientation="Horizontal" VerticalAlignment="Bottom" HorizontalAlignment="Right" Margin="10,0,10,10">
          <Button Height="30" Width="70" Content="Close" Margin="10,0,0,0"/>
          <Button Height="30" Width="70" Content="Save" Margin="10,0,0,0" Click="AddUser"/>
        </StackPanel>
      </Grid>
    </Window>
    
    using System.Windows;
    using WpfControlLibrary094.Add_Edit_Delete.ViewModel;
    
    namespace WpfControlLibrary1
    {
      public partial class Window094A : Window
      {
        public Window094A() => InitializeComponent();
        private void AddUser(object sender, RoutedEventArgs e) => ((AddViewModel)this.DataContext).AddUser();
      }
    }
    

    <UserControl x:Class="WpfControlLibrary1.Window094UC1"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
                 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
                 xmlns:local="clr-namespace:WpfControlLibrary1"
                 xmlns:local1="clr-namespace:WpfControlLibrary094.Add_Edit_Delete.ViewModel"
                 mc:Ignorable="d" 
                 d:DesignHeight="450" d:DesignWidth="800">
      <Grid>
        <Grid.ColumnDefinitions>
          <ColumnDefinition Width="*"/>
          <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <ListView Grid.Column="0" ItemsSource="{Binding ListOfUser}">
          <ListView.View>
            <GridView>
              <GridViewColumn Header="Firstname" x:Name="Firstname" Width="200">
                <GridViewColumn.CellTemplate>
                  <DataTemplate>
                    <TextBlock Text="{Binding Firstname}" TextWrapping="Wrap"/>
                  </DataTemplate>
                </GridViewColumn.CellTemplate>
              </GridViewColumn>
              <GridViewColumn Header="Lastname" x:Name="Lastname" Width="200">
                <GridViewColumn.CellTemplate>
                  <DataTemplate>
                    <TextBlock Text="{Binding Lastname}" TextWrapping="Wrap"/>
                  </DataTemplate>
                </GridViewColumn.CellTemplate>
              </GridViewColumn>
            </GridView>
          </ListView.View>
        </ListView>
        <StackPanel Grid.Column="1" Orientation="Horizontal" VerticalAlignment="Top" Margin="20,0,0,0">
          <Button Height="25" Width="50" Content="Add" Margin="10" Click="Add_Click"/>
          <Button Height="25" Width="50" Content="Edit" Margin="10" Click="Eddit_Click"/>
          <Button Height="25" Width="50" Content="Delete" Margin="10" Click="Delete_Click" />
        </StackPanel>
      </Grid>
    </UserControl>
    
    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using System.Windows;
    using System.Windows.Controls;
    using WpfControlLibrary094.Add_Edit_Delete.ViewModel;
    using WpfControlLibrary1;
    
    namespace WpfControlLibrary1
    {
      public partial class Window094UC1 : UserControl
      {
        public Window094UC1()
        {
          InitializeComponent();
          DataContext = _userViewModel;
        }
        UserViewModel _userViewModel = new UserViewModel();
        private void Add_Click(object sender, RoutedEventArgs e) => _userViewModel.CmdExec("Add_Click");
        private void Eddit_Click(object sender, RoutedEventArgs e) => _userViewModel.CmdExec("Eddit_Click");
        private void Delete_Click(object sender, RoutedEventArgs e) => _userViewModel.CmdExec("Delete_Click");
      }
    }
    
    namespace WpfControlLibrary094.Add_Edit_Delete.ViewModel
    {
      public class UserModel
      {
        public int Id { get; set; }
        public string Firstname { get; set; }
        public string Lastname { get; set; }
      }
    
      public class UserViewModel
      {
        public ObservableCollection<UserModel> ListOfUser { get; set; } = new ObservableCollection<UserModel>();
        internal void CmdExec(object obj)
        {
          switch (obj.ToString())
          {
            case "Add_Click":
              Window094A oAdd = new Window094A();
              AddViewModel vm = new AddViewModel(this);
              oAdd.DataContext = vm;
              oAdd.Owner = Application.Current.MainWindow;
              oAdd.ShowDialog();
              break;
            default:
              break;
          }
        }
      }
    
      public class AddViewModel : INotifyPropertyChanged
      {
        public AddViewModel(UserViewModel vm) => mainVm = vm;
    
        internal void AddUser()
        {
          mainVm.ListOfUser.Add(NewUser);
          NewUser = new UserModel();
          PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(NewUser)));
        }
    
        private UserViewModel mainVm;
    
        public UserModel NewUser { get; set; } = new UserModel();
    
        public event PropertyChangedEventHandler PropertyChanged;
      }
    }
    

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.