绑定到BindingList(或ObservableCollection)的DataGrid不会更新

时间:2017-03-27 10:02:57

标签: c# wpf xaml data-binding datagrid

我在SO上尝试了很多解决方案,但没有一个适合我。 DataGrid永远不会更新。

我有一个类(UserTab)从UserControl继承了XAML,一个类带有数据(TableController)。

XAML(UserTab):

<local:BaseTab.Resources>
        <ResourceDictionary>
            <controller:TableController x:Key="tablecontroller" />
        </ResourceDictionary>
</local:BaseTab.Resources>

<DataGrid x:Name="dataGrid"
          IsReadOnly="True"
          ItemsSource="{Binding Path=FilteredEntries, Source={StaticResource tablecontroller}}"
          SelectionUnit="Cell"
          AutoGenerateColumns="False">
          <DataGrid.Columns>
                <DataGridTextColumn Binding="{Binding id}"
                                    Header="{StaticResource id}" />
                <DataGridTextColumn Binding="{Binding name}"
                                    Header="{StaticResource name}" />
                <DataGridTextColumn Binding="{Binding desc}"
                                    Header="{StaticResource desc}" />
          </DataGrid.Columns>
</DataGrid>

我也尝试过更改ModeUpdateSourceTrigger

TableController

public class TableController : INotifyPropertyChanged
{
    private IList<entry> _allEntries;
    private BindingList<entry> _filteredEntries = new BindingList<entry>();

    public IList<entry> AllEntries
    {
        get
        {
            return _allEntries;
        }
        set
        {
            _allEntries = value;
        }
    }
    public BindingList<entry> FilteredEntries
    {
        get
        {
            return _filteredEntries;
        }
        set
        {
            _filteredEntries = value;
            NotifyPropertyChanged("FilteredEntries");
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public void NotifyPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    private void LoadData()
    {
        using (var dbContext = new InventarDBEntities())
        {
            AllEntries = dbContext.entry.OrderBy(x => x.name).ToList();
            //FilteredEntries = new BindingList<entry>(AllEntries);
        }
    }

    public void TestMethod()
    {
        foreach (entry entry in AllEntries)
        {
            FilteredEntries.Add(entry);
        }
    }
}

FilteredEntries以后只包含AllEntries的子列表。我用这段代码来测试绑定。第一个FilteredEntries为空,DataGrid也为空。单击按钮并触发TestMethod FilteredEntries包含条目,但DataGrid仍为空。我还尝试了ObservableCollection并在UserTab.xaml.cs中创建了一个属性,只是从FilteredEntries转发TableController。没有任何效果。

更新 似乎第一个Binding不起作用,因为当我通过代码设置ItemSource时,它会在更改List时更新。

1 个答案:

答案 0 :(得分:1)

FilteredEntries属性的类型更改为ObservableCollection<entry>,并在NotifyPropertyChanged属性的设置器中调用AllEntries方法:

public class TableController : INotifyPropertyChanged
{
    private IList<entry> _allEntries;
    private ObservableCollection<entry> _filteredEntries = new ObservableCollection<entry>();

    public IList<entry> AllEntries
    {
        get
        {
            return _allEntries;
        }
        set
        {
            _allEntries = value;
            NotifyPropertyChanged("AllEntries");
        }
    }
    public ObservableCollection<entry> FilteredEntries
    {
        get
        {
            return _filteredEntries;
        }
        set
        {
            _filteredEntries = value;
            NotifyPropertyChanged("FilteredEntries");
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public void NotifyPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    private void LoadData()
    {
        using (var dbContext = new InventarDBEntities())
        {
            AllEntries = dbContext.entry.OrderBy(x => x.name).ToList();
            //FilteredEntries = new BindingList<entry>(AllEntries);
        }
    }

    public void TestMethod()
    {
        foreach (entry entry in AllEntries)
        {
            FilteredEntries.Add(entry);
        }
    }
}
  

这不起作用。它必须是绑定而不是更新。当我将dataGrid的dataContext设置为TableController.FilteredEntries时,它可以工作并显示所有更新

当然,您必须将DataContext或其任何父元素的DataGrid设置为TableController类的实例,以便能够绑定到它。

我不知道你为什么要绑定资源。您不应将TableController添加为资源,而是将其设置为元素的DataContext

<local:BaseTab.DataContext>
    <controller:TableController />
</local:BaseTab.Resources>

<DataGrid x:Name="dataGrid"
      IsReadOnly="True"
      ItemsSource="{Binding Path=FilteredEntries}"
      SelectionUnit="Cell"
      AutoGenerateColumns="False">
...

或者:

<DataGrid x:Name="dataGrid"
          IsReadOnly="True"
          ItemsSource="{Binding Path=FilteredEntries}"
          SelectionUnit="Cell"
          AutoGenerateColumns="False">
    <DataGrid.DataContext>
        <controller:TableController />
    </DataGrid.DataContext>
    ...
</DataGrid>