WPF DataGrid not updating on PropertyChanged
Asked Answered
L

3

13

i've a problem updating my datagrid when clicking the button by using NotifyPropertyChanged. It works if i set the DataGrid.ItemsSource in code behind, but it doesn't if i set it in xaml. here's some code of code behind & xaml:

namespace MyWpfDataBindingLab
{
public partial class NpcWindow : Window
{
    DataCollection dc = new DataCollection();

    public NpcWindow()
    {
        InitializeComponent();
        //command binding code
        //...
    }

    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        //if i set the ItemsSource here, updating of the UI works
        //dataGrid1.ItemsSource = dc;
    }

    private void CmdCollectionChangedExecute(object sender, ExecutedRoutedEventArgs e)
    {
        foreach (SampleClass s in dc)
        {
            s.Property1 = "changed";
            s.Property3 = "changed";
            s.Property3 = "changed";
            break;
        }

        dc.Add(new SampleClass("new sample 1", "new sample 2", "new sample 3"));
    }
}
}

<Window x:Class="WPFDataBinding.NpcWindow"
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:npc="clr-namespace:WPFDataBinding.NotifyPropChanged"
    Title="MainWindow" Height="189" Width="459" Loaded="Window_Loaded">
<Window.Resources>
    <npc:DataCollection x:Key="dataCol"/>
</Window.Resources>
<Grid>
    <Grid.ColumnDefinitions>
    </Grid.ColumnDefinitions>
    <Button Content="Button" Height="23" HorizontalAlignment="Left" Margin="349,110,0,0" Name="button1" VerticalAlignment="Top" Width="75" />
    <!-- if i set the ItemsSource here, updating of the UI doesn't work -->
    <DataGrid ItemsSource="{Binding Source={StaticResource dataCol}, Mode=OneWay, NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged}"
              AutoGenerateColumns="True" Height="103" HorizontalAlignment="Left" Margin="12,12,0,0" Name="dataGrid1" VerticalAlignment="Top" Width="331" />
</Grid>

my data & NotifyPropertyChanged implementation:

namespace MyWpfDataBindingLab.NotifyPropChanged
{    
public class SampleClass : NotifyPropertyChanged
{
    private string _field1;
    private string _field2;
    private string _field3;

    public string Property1
    { 
        get { return _field1; } 
        set 
        {
            _field1 = value;
            OnPropertyChanged("Property1");
        }
    }

    public string Property2
    { 
        get { return _field2; } 
        set 
        {
            _field2 = value;
            OnPropertyChanged("Property2");
        }
    }

    public string Property3
    { 
        get { return _field3; } 
        set 
        {
            _field3 = value;
            OnPropertyChanged("Property3");
        }
    }

    public SampleClass()
    {
        _field1 = "value1";
        _field2 = "value2";
        _field3 = "value3";
    }

    public SampleClass(string p1, string p2, string p3)
    {
        _field1 = p1;
        _field2 = p2;
        _field3 = p3;
    }
}
}

namespace MyWpfDataBindingLab.NotifyPropChanged
{
public abstract class NotifyPropertyChanged : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;

        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}
}

namespace MyWpfDataBindingLab.NotifyPropChanged
{
public class DataCollection : ObservableCollection<SampleClass> 
{
    public DataCollection()
    {
        this.Add(new SampleClass());
        this.Add(new SampleClass());
        this.Add(new SampleClass());
    }
}
}

i have no idea what the problem is. i'd appreciate it if someone can help solving my problem.

Limpopo answered 8/9, 2012 at 8:24 Comment(2)
Do you have any code that actually adds items to the instance of DataCollection? If you add nothing then the CmdCollectionChangedExecute handler won't fire.Accompanist
the collection is updated via CmdCollectionChangedExecute when clicking the button. the method name is a little confusing. it shoud be CmdCollectionChangeExecute. updating works fine, but the ui is only updating if set the ItemsSource in code behind. i like to do it only in the xaml file.Limpopo
U
15

In your codebehind .xaml.cs create property

   public ObservableCollection<SampleClass> MyCollection {get; set;}

   private void Window_Loaded(object sender, RoutedEventArgs e)
   {
    //if i set the ItemsSource here, updating of the UI works
      dataGrid1.ItemsSource = MyCollection;
   }

In XAML:

   <DataGrid ItemsSource="{Binding Path=., Mode=OneWay, NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged}"/>
Unwished answered 8/9, 2012 at 8:38 Comment(3)
thanks for the quick answer. your code is working well. is it possible to get rid of the dataGrid1.ItemsSource = MyCollection; in code behind, and do the complete binding in xaml?Limpopo
You can use this.DataContext = MyCollection;Unwished
Thanks! This is just what I was looking for - solved my problem quite nicely.Crystlecs
B
10

I followed up on syned's tip. For me I had to us the Mode as

Mode=TwoWay

The key here was the

UpdateSourceTrigger

property.

Thanks a lot...!

Blacksnake answered 22/5, 2014 at 15:9 Comment(0)
P
2

When you go crazy (like me) because it doesn't work this time (while it always worked!) Check the order of the calls. The OnPropertyChanged() must be called after the value was assigned.

public string Property1
{ 
    get { return _field1; } 
    set 
    {
        // assign the value first ...
        _field1 = value;

        // ... then call the property changed
        OnPropertyChanged(nameof(Property1));
    }
}
Printmaking answered 13/5, 2020 at 19:23 Comment(1)
Thank you, that was my exact problem, didn't see this before your solution.Custombuilt

© 2022 - 2024 — McMap. All rights reserved.