WPF DataGrid在属性更改时没有更新

13

我在使用NotifyPropertyChanged时,遇到了点击按钮更新数据表格的问题。如果我在代码中设置DataGrid.ItemsSource,它可以正常工作,但如果我在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>

我的数据和NotifyPropertyChanged实现:

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());
    }
}
}

我不知道问题出在哪里。如果有人能帮我解决问题,我将非常感激。


你有任何将项添加到“DataCollection”实例的代码吗?如果您没有添加任何内容,则“CmdCollectionChangedExecute”处理程序不会触发。 - slugster
当单击按钮时,集合通过CmdCollectionChangedExecute进行更新。方法名称有点令人困惑。它应该是CmdCollectionChangeExecute。更新工作正常,但UI仅在代码后台中设置ItemsSource时才会更新。我希望只在xaml文件中完成。 - nllpntr
3个回答

15
在您的代码后台 .xaml.cs 中创建属性。
   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;
   }
在XAML中:
   <DataGrid ItemsSource="{Binding Path=., Mode=OneWay, NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged}"/>

感谢您的快速回复。您的代码运行良好。在代码后台中,是否有可能去掉“dataGrid1.ItemsSource = MyCollection;”,并在XAML中完成完整的绑定? - nllpntr
您可以使用此.DataContext = MyCollection; - syned
谢谢!这正是我在寻找的 - 很好地解决了我的问题。 - Fred

10

我跟进了syned的提示。对我来说,我必须使用Mode

Mode=TwoWay

关键在于这里的

UpdateSourceTrigger

属性。

非常感谢...!


2
当你因为某个东西不起作用而变得疯狂(就像我一样),请检查调用的顺序。在赋值之后必须调用OnPropertyChanged()方法。
public string Property1
{ 
    get { return _field1; } 
    set 
    {
        // assign the value first ...
        _field1 = value;

        // ... then call the property changed
        OnPropertyChanged(nameof(Property1));
    }
}

谢谢,那正是我的问题,没有在您的解决方案之前看到。 - dennis_ler

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接