Elham Azadfar
Elham Azadfar

Reputation: 737

How to Update DataGrid ItemsSource when change its Property?

This is an example code:

public class GridViewWindowViewModel : INotifyPropertyChanged
    {
        public GridViewWindowViewModel()
        {
            Tables = new ObservableCollection<string> { "Person", "Car" };
            SainaAccessEntity = new SainaAccessEntity { TableName = "Person" };
        }

        private SainaAccessEntity _SainaAccessEntity;

        public SainaAccessEntity SainaAccessEntity
        {
            get { return _SainaAccessEntity; }
            set
            {
                if (_SainaAccessEntity != value)
                {
                    _SainaAccessEntity = value;
                    OnPropertyChanged();
                }
            }
        }

        private ObservableCollection<string> _Tables;

        public ObservableCollection<string> Tables
        {
            get { return _Tables; }
            set
            {
                if (_Tables != value)
                {
                    _Tables = value;
                    OnPropertyChanged();
                }
            }
        }

        public event PropertyChangedEventHandler PropertyChanged = delegate { };
        private void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

    }

this is Model Class :

public class SainaAccessEntity : INotifyPropertyChanged
    {
        private string _TableName;

        public string TableName
        {
            get { return _TableName; }
            set
            {
                if (value != _TableName)
                {
                    _TableName = value;
                    OnPropertyChanged();
                }
            }
        }

        public event PropertyChangedEventHandler PropertyChanged = delegate { };
        private void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

Custom Data Grid View:

public class MyDataGrid : DataGrid
{
    public MyDataGrid()
    {
        var x = new ObservableCollection<Person> { new Person { Name = "Ali", Family = "Jalilvand" } };
    }
    public SainaAccessEntity SainaAccessEntity
    {
        get { return (SainaAccessEntity)GetValue(SainaAccessEntityProperty); }
        set { SetValue(SainaAccessEntityProperty, value); }
    }
    public static readonly DependencyProperty SainaAccessEntityProperty =
        DependencyProperty.Register("SainaAccessEntity", typeof(SainaAccessEntity), typeof(MyDataGrid), new PropertyMetadata(null, SainaAccessEntity_Changed));

    private static void SainaAccessEntity_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var u = d as MyDataGrid;
        if (u.SainaAccessEntity.TableName == "Person")
        {
            u.ItemsSource = new ObservableCollection<Person> { new Person { Name = "Ali", Family = "Bayat" } };
        }
        else
        {
            u.ItemsSource = new ObservableCollection<Car1> { new Car1 { Name = "BMW", Model = "518",Color="Red" } };
        }

    }

}

Car And Person Model:

public class Car1
{
    public string Model { get; set; }
    public string Name { get; set; }
    public string Color { get; set; }

}

public class Person
{
    public string Name { get; set; }
    public string Family { get; set; }
}

Main Window XAML:

<Window x:Class="TestWpfApplication.GridViewWindow"
        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:TestWpfApplication"
        mc:Ignorable="d"
        Title="GridViewWindow" Height="300" Width="300">
    <Window.Resources>
        <local:GridViewWindowViewModel x:Key="Vm"/>
    </Window.Resources>
    <Grid DataContext="{StaticResource Vm}">
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="auto"/>
        </Grid.RowDefinitions>
        <local:MyDataGrid  VerticalAlignment="Top" SainaAccessEntity="{Binding SainaAccessEntity, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
        <ComboBox Margin="0,5.694,0,0" Grid.Row="1" ItemsSource="{Binding Tables, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" SelectedItem="{Binding SainaAccessEntity.TableName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></ComboBox>
    </Grid>
</Window>

How to Update DataGrid ItemsSource when change its Property? I have Custom DataGrid in WPF, it has a Property that define table name, and I want to dynamically change ItamsSource, when change this Property...

Upvotes: 1

Views: 3445

Answers (2)

mm8
mm8

Reputation: 169390

The SainaAccessEntity property of your custom DataGrid is bound to the SainaAccessEntity property of the view model but you never set this property when the selection in the ComboBox changes.

The Tables property of the view model should return an ObservableCollection<SainaAccessEntity> instead of an ObservableCollection<string>:

public class GridViewWindowViewModel : INotifyPropertyChanged
{
    public GridViewWindowViewModel()
    {
        Tables = new ObservableCollection<SainaAccessEntity>
            {
                new SainaAccessEntity { TableName = "Person" },
                new SainaAccessEntity { TableName = "Car" },
            };
        SainaAccessEntity = Tables[0];
    }

    private SainaAccessEntity _SainaAccessEntity;

    public SainaAccessEntity SainaAccessEntity
    {
        get { return _SainaAccessEntity; }
        set
        {
            if (_SainaAccessEntity != value)
            {
                _SainaAccessEntity = value;
                OnPropertyChanged();
            }
        }
    }

    private ObservableCollection<SainaAccessEntity> _Tables;
    public ObservableCollection<SainaAccessEntity> Tables
    {
        get { return _Tables; }
        set
        {
            if (_Tables != value)
            {
                _Tables = value;
                OnPropertyChanged();
            }
        }
    }

    public event PropertyChangedEventHandler PropertyChanged = delegate { };
    private void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}

You should then bind the SelectedItem property of the ComboBox to the SainaAccessEntity property of the view model and set the DisplayMemberPath property of the ComboBox to "TableName":

<ComboBox Margin="0,5.694,0,0" Grid.Row="1" ItemsSource="{Binding Tables, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" 
                  SelectedItem="{Binding SainaAccessEntity, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                  DisplayMemberPath="TableName"></ComboBox>

With these changes the ItemsSource of the DataGrid should be changed as expected when you select an item in the ComboBox.

Upvotes: 3

Maulik Parmar
Maulik Parmar

Reputation: 892

Here your property 'SainaAccessEntity' is not changing, only TableName is changing. For that you can try below code or you can change type from 'SainaAccessEntity' to string.

change 'SainaAccessEntity_Changed' method's code

        var u = d as MyDataGrid;

        if (u.SainaAccessEntity == null)
        {
            return;
        }

        // intial set value
        if (u.SainaAccessEntity.TableName == "Person")
        {
            u.ItemsSource = new ObservableCollection<Person> { new Person { Name = "Ali", Family = "Bayat" } };
        }
        else
        {
            u.ItemsSource = new ObservableCollection<Car1> { new Car1 { Name = "BMW", Model = "518", Color = "Red" } };
        }

        // set value on change
        var _notify = u.SainaAccessEntity as INotifyPropertyChanged;
        if (_notify != null)
        {
            _notify.PropertyChanged += (sender, ev) =>
            {
                if (u.SainaAccessEntity.TableName == "Person")
                {
                    u.ItemsSource = new ObservableCollection<Person> { new Person { Name = "Ali", Family = "Bayat" } };
                }
                else
                {
                    u.ItemsSource = new ObservableCollection<Car1> { new Car1 { Name = "BMW", Model = "518", Color = "Red" } };
                }
            };
        }

Upvotes: 2

Related Questions