WPF Core - DataGrid CurrentItem for DataContext of Another Grid?

Faraz Qureshi 116 Reputation points
2020-09-05T07:12:52.59+00:00

Hi friends,
While going through a WPF Core project for CRUD as I came across an example I found that having a Button being placed in a datagrid, against each record, I could implement to the click event a procedure, like the following, to place the data of the same to another grid containing the controls for editing a record:

        private void eExclEdit(object sender, RoutedEventArgs e)
        {
            EditAccNat = (sender as FrameworkElement).DataContext as AccountNature;
            GridForEdit.DataContext = EditAccNat;
        }

However, trying to avoid using a number of buttons via DataGridTemplateColumn as I tried a number of times to have a similar procedure being tagged to an event of SelectionChanged in a code like the follows, I found the implementation of datacontext failed. Most probably because of the context returned in respect of the Entire Collection of data pertaining to AccountNatures???

        private void eAccNatSelectedChanged(object sender, SelectionChangedEventArgs e)
        {
            EditAccNat = (sender as FrameworkElement).DataContext as AccountNature;
            GridForEdit.DataContext = EditAccNat;
        }

An example of achieving the same shall be appreciated.
Thanks in advance.

Windows Presentation Foundation
Windows Presentation Foundation
A part of the .NET Framework that provides a unified programming model for building line-of-business desktop applications on Windows.
2,185 questions
No comments
{count} votes

Accepted answer
  1. Faraz Qureshi 116 Reputation points
    2020-09-05T18:22:51.407+00:00

    Sorry buddy but despite of trying for 4-5 hours wasn't able to comprehend and implement your example.
    Inconvenience of any sort is regretted.

    However, referring to Mathew MacDonald's Pro WPF 4.5 in C# and tracing out an example like

    Type type = (Type)lstTypes.SelectedItem;
    

    modified to:

    private void eAccNatSelectedChanged(object sender, SelectionChangedEventArgs e)
    {
        EditAccNat = (AccountNature)dgrd_AccNat.SelectedItem;
        GridForEdit.DataContext = EditAccNat;
    }
    

    did resolve the said query.

    :-)


2 additional answers

Sort by: Most helpful
  1. Peter Fleischer (Freelancer) 17,571 Reputation points
    2020-09-05T09:05:59.277+00:00

    Hi Faraz,
    without Button you can use CurrentItem in DataGrid for Binding to another Grid like in following demo

    XAML:

    <Window x:Class="WpfApp1.Window80"  
            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:WpfApp80"  
            mc:Ignorable="d"  
            Title="Window80" Height="450" Width="800">  
      <Window.DataContext>  
        <local:ViewModel/>  
      </Window.DataContext>  
      <Grid>  
        <Grid.ColumnDefinitions>  
          <ColumnDefinition/>  
          <ColumnDefinition/>  
        </Grid.ColumnDefinitions>  
        <DataGrid ItemsSource="{Binding View}" IsReadOnly="True"/>  
        <Grid Grid.Column="1" DataContext="{Binding Detail}">  
          <Grid.ColumnDefinitions>  
            <ColumnDefinition/>  
            <ColumnDefinition/>  
          </Grid.ColumnDefinitions>  
          <Grid.RowDefinitions>  
            <RowDefinition Height="Auto"/>  
            <RowDefinition Height="Auto"/>  
            <RowDefinition/>  
          </Grid.RowDefinitions>  
          <Label Grid.Row="0" Grid.Column="0" Content="ID: " HorizontalAlignment="Right"/>  
          <TextBox Grid.Row="0" Grid.Column="1" Text="{Binding ID}" IsReadOnly="True"/>  
          <Label Grid.Row="1" Grid.Column="0" Content="Info: " HorizontalAlignment="Right"/>  
          <TextBox Grid.Row="1" Grid.Column="1" Text="{Binding Info}"/>  
        </Grid>  
      </Grid>  
    </Window>  
    

    and Code:

    using System;  
    using System.Collections.ObjectModel;  
    using System.ComponentModel;  
    using System.Runtime.CompilerServices;  
    using System.Windows;  
    using System.Windows.Data;  
      
    namespace WpfApp04  
    {  
      public class ViewModel : INotifyPropertyChanged  
      {  
        private CollectionViewSource cvs = new CollectionViewSource();  
        private ObservableCollection<Data> col = new ObservableCollection<Data>();  
        public ICollectionView View  
        {  
          get  
          {  
            if (cvs.Source == null)  
            {  
              GetData();  
              cvs.View.CurrentChanged += (sender, e) => Detail = cvs.View.CurrentItem as Data;  
            }  
            return cvs.View;  
          }  
        }  
      
        private Data _detail = null;  
        public Data Detail { get => this._detail; set { this._detail = value; OnPropertyChanged(); } }  
      
        private void GetData()  
        {  
          for (int i = 1; i < 11; i++)  
            col.Add(new Data { ID = i, Info = $"Row {i}" });  
          cvs.Source = col;  
        }  
      
        public event PropertyChangedEventHandler PropertyChanged;  
        private void OnPropertyChanged([CallerMemberName] String propertyName = "") =>  
          PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));  
      }  
      
      public class Data  
      {  
        public int ID { get; set; }  
        public string Info { get; set; }  
      }  
    }  
    

    Result:

    22728-x.gif

    No comments

  2. Peter Fleischer (Freelancer) 17,571 Reputation points
    2020-09-05T09:39:35.873+00:00

    Hi Faraz,
    with Button in DataGrid column you can use command binding to set the DataContext in another Grid like in following demo:

    XAML:

    <Window x:Class="WpfApp1.Window05"  
            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:WpfApp05"  
            mc:Ignorable="d"  
            Title="DataGrid with Button column and row details Grid" Height="450" Width="800">  
      <Window.Resources>  
        <local:ViewModel x:Key="vm"/>  
      </Window.Resources>  
      <Grid DataContext="{StaticResource vm}">  
        <Grid.ColumnDefinitions>  
          <ColumnDefinition/>  
          <ColumnDefinition/>  
        </Grid.ColumnDefinitions>  
        <DataGrid ItemsSource="{Binding View}" AutoGenerateColumns="False"  IsReadOnly="True">  
          <DataGrid.Columns>  
            <DataGridTemplateColumn Header="Select">  
              <DataGridTemplateColumn.CellTemplate>  
                <DataTemplate>  
                  <StackPanel>  
                    <Button Content="{Binding ID}" Command="{Binding Source={StaticResource vm}}" CommandParameter="{Binding}"/>  
                  </StackPanel>  
                </DataTemplate>  
              </DataGridTemplateColumn.CellTemplate>  
            </DataGridTemplateColumn>  
            <DataGridTextColumn Header="Info" Binding="{Binding Info}"/>  
          </DataGrid.Columns>  
        </DataGrid>  
        <Grid Grid.Column="1" DataContext="{Binding Detail}">  
          <Grid.ColumnDefinitions>  
            <ColumnDefinition/>  
            <ColumnDefinition/>  
          </Grid.ColumnDefinitions>  
          <Grid.RowDefinitions>  
            <RowDefinition Height="Auto"/>  
            <RowDefinition Height="Auto"/>  
            <RowDefinition/>  
          </Grid.RowDefinitions>  
          <Label Grid.Row="0" Grid.Column="0" Content="ID: " HorizontalAlignment="Right"/>  
          <TextBox Grid.Row="0" Grid.Column="1" Text="{Binding ID}" IsReadOnly="True"/>  
          <Label Grid.Row="1" Grid.Column="0" Content="Info: " HorizontalAlignment="Right"/>  
          <TextBox Grid.Row="1" Grid.Column="1" Text="{Binding Info}"/>  
        </Grid>  
      </Grid>  
    </Window>  
    

    Code:

    using System;  
    using System.Collections.ObjectModel;  
    using System.ComponentModel;  
    using System.Runtime.CompilerServices;  
    using System.Windows;  
    using System.Windows.Data;  
    using System.Windows.Input;  
      
    namespace WpfApp05  
    {  
      public class ViewModel : ICommand, INotifyPropertyChanged  
      {  
        private CollectionViewSource cvs = new CollectionViewSource();  
        private ObservableCollection<Data> col = new ObservableCollection<Data>();  
        public ICollectionView View  
        {  
          get  
          {  
            if (cvs.Source == null) GetData();  
            return cvs.View;  
          }  
        }  
      
        private object _detail = null;  
        public object Detail { get => this._detail; set { this._detail = value; OnPropertyChanged(); } }  
      
        private void GetData()  
        {  
          for (int i = 1; i < 11; i++)  
            col.Add(new Data { ID = i, Info = $"Row {i}" });  
          cvs.Source = col;  
        }  
      
        public event PropertyChangedEventHandler PropertyChanged;  
      
        private void OnPropertyChanged([CallerMemberName] String propertyName = "") =>  
          PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));  
      
        public void Execute(object parameter) => Detail = parameter;  
        public event EventHandler CanExecuteChanged;  
        public bool CanExecute(object parameter) => true;  
      }  
      
      public class Data  
      {  
        public int ID { get; set; }  
        public string Info { get; set; }  
      }  
    }  
    

    Result:

    22831-x.gif

    No comments