Search code examples
c#wpfdatagrid

How can i add a record to a datagrid and update it from another window?


I'm having a problem with updating the contents of a datagrid. I want to add a row to a datagrid from another window in which the user fills in the information. Then when clicking a button, the datagrid should update and show the added row. Right now however, it doesn't and i can't figure out what i'm doing wrong.

This is what it looks like So when adding an account it should update the datagrid in the main window with the newly added record.

Right now this is how i add a record when i want to do it from the same window (which works fine)

    public ObservableCollection<Account> ListAccountInfo { get; } = new ObservableCollection<Account>();

    public MainWindow()
    {
        InitializeComponent();
        ListAccountInfo.Add(new Account
        {
            IsSelected = true,
            qweqwe = "test123",
            qweqwe = "test123",
            qwe = "N/A",
            qwe = "N/A",
            qwe = "N/A",
            qwe = "N/A",
            qwe = "N/A",
            qwe = "N/A"
        });
    }

But when i try to do the same thing from the code behind in the other window (the one with the form), it doesn't add the new record to the list.

The Account class is just a bunch of get; set;. Doesn't contain anything else (i can add it if needed..)

I hope someone can help me with this. I'm not that experienced with wpf yet ❤


Solution

  • Easiest solution is to use a shared DataContext instance for both windows and an ICommand to actually add the new Account item to the collection:

    RelayCommand.cs
    Implementation taken from Microsoft Docs: Patterns - WPF Apps With The Model-View-ViewModel Design Pattern - Relaying Command Logic

    public class RelayCommand : ICommand
    {
        #region Fields 
        readonly Action<object> _execute;
        readonly Predicate<object> _canExecute;
        #endregion // Fields 
        #region Constructors 
        public RelayCommand(Action<object> execute) : this(execute, null) { }
        public RelayCommand(Action<object> execute, Predicate<object> canExecute)
        {
            if (execute == null)
                throw new ArgumentNullException("execute");
            _execute = execute; _canExecute = canExecute;
        }
        #endregion // Constructors 
        #region ICommand Members 
        [DebuggerStepThrough]
        public bool CanExecute(object parameter)
        {
            return _canExecute == null ? true : _canExecute(parameter);
        }
        public event EventHandler CanExecuteChanged
        {
            add { CommandManager.RequerySuggested += value; }
            remove { CommandManager.RequerySuggested -= value; }
        }
        public void Execute(object parameter) { _execute(parameter); }
        #endregion // ICommand Members 
    }
    

    ViewModel.cs

    public class ViewModel : INotifyPropertyChanged
    {
      public ViewModel()
      {
        this.NewAccount = new Account();
        this.ListAccountInfo = new ObservableCollection<Account>()
        {
          new Account
          {
            IsSelected = true,
            Username = "test123",
            qweqwe = "test123",
            qwe = "N/A",
            qwe = "N/A",
            qwe = "N/A",
            qwe = "N/A",
            qwe = "N/A",
            qwe = "N/A"
          }
        };
      }
    
      public ObservableCollection<Account> ListAccountInfo { get; }
    
      private Account newAccount;
      public Account NewAccount
      {
        get => this.newAccount;
        set
        {
          this.newAccount = value;
          OnPropertyChanged();
        }
      }
    
      public ICommand AddAccountCommand 
      { 
        get => new RelayCommand(
          param => 
          {
            this.ListAccountInfo.Add(this.NewAccount);
            this.NewAccount = new Account();
          });  
      }
    
      #region Implementation of INotifyPropertyChanged
    
      public event PropertyChangedEventHandler PropertyChanged;
    
      [NotifyPropertyChangedInvocator]
      protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
      {
        this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
      }
      #endregion Implementation of INotifyPropertyChanged
    
    }
    

    App.xaml

    <Application>
      <Application.Resources>
    
        <!-- Globally shared ViewModel instance -->
        <ViewModel x:Key="ViewModel" />  
      </Application.Resources>
    </Application>
    

    MainWindow.xaml

    <Window>
      <Window.DataContext>
        <StaticResource ResourceKey="ViewModel" />
      </Window.DatContext>
    
      <DataGrid ItemsSource="{Binding ListAccountInfo}" />
    </Window>
    

    DialogWindow.xaml

      <Window.DataContext>
        <StaticResource ResourceKey="ViewModel" />
      </Window.DatContext>
    
      <StackPanel>
        <TextBox Text="{Binding NewAccount.Username}" />
        <Button Content="Add" 
                Command="{Binding AddAccountCommand}" />   
      </StackPanel>
    </Window>