首页 > 解决方案 > WPF:ItemSource 未显示任何项目

问题描述

WPF 的一段代码非常简单:

<telerik:RadGridView Name="AnalisiKey" 
                              AutoGenerateColumns="True"
                                         Margin="10,273,694,59" 
                              d:DataContext="{d:DesignInstance Type=viewModels:FrequentKeywordFinderViewModel, IsDesignTimeCreatable=True}"
                              ItemsSource="{Binding ItemCollectionViewSourceSingole}" 
                              ClipboardCopyMode="All" SelectionMode="Extended" SelectionUnit="Mixed">
      <!--<telerik:RadGridView.Columns>
        <telerik:GridViewDataColumn  x:Name="Keyword" Header="Keyword" Language="it-it" DataMemberBinding="{Binding (viewModels:KeyFreq.Keyword)}" />
        <telerik:GridViewDataColumn x:Name="FreqNelDocum" Header="FreqNelDocum" Language="it-it" UniqueName="FreqNelDocum"/>
      </telerik:RadGridView.Columns>-->
    </telerik:RadGridView>

以及 ViewModel

class FrequentKeywordFinderViewModel : MarkupExtension
  {
    public override object ProvideValue(IServiceProvider serviceProvider) => this;

    public List<KeyFreq> ItemCollectionViewSourceSingole { get; set; } = new List<KeyFreq>();
  }

以及填充 ItemSource 的代码:

 private void MostroRisultatiSuGriglia(List<KeyFreq> singole,
          List<KeyFreq> doppie, bool excludeUnfrequentKeys)
        {
          var dataContext = ((FrequentKeywordFinderViewModel)this.DataContext);
          var itemCollectionViewSourceSingole = dataContext.ItemCollectionViewSourceSingole;

          singole = CalcolaTfIdf(StopWordsUtil.FrequenzaKeywords, singole);

            dataContext.ItemCollectionViewSourceSingole.AddRange(singole.Where(s => s.FreqNelDocum > 1).ToList());
            itemCollectionViewSourceDoppie.Source = doppie.Where(s => s.FreqNelDocum > 1).ToList();              

        }

使用 Snoop,我可以深入研究 datagrid.ItemSource 并查看项目。但它们不会出现在数据网格中。有什么建议吗?

在此处输入图像描述

标签: c#.netwpfdatagrid

解决方案


使用绑定时要注意的一个关键点是控件不会从绑定的属性中更新,除非并且直到它被通知值已更改。实现此通知有两种基本方法:

  1. 继承您的 ViewModel并在您的属性值更改时INotifyPropertyChanged调用该事件。PropertyChanged这种方法适用于大多数情况,包括绑定到控件的数字和字符串属性,例如TextBlockTextBox

  2. 用于ObservableCollection绑定到ItemsSource属性的集合(用于具有ItemsSource属性的控件)。

控件知道INotifyPropertyChanged接口和INotifyCollectionChanged底层接口ObservableCollection,并监听相应的PropertyChanged事件CollectionChanged

选择适当技术的指南如下:

  • 如果 ViewModel 中的属性值是在控件DataContext设置为 ViewModel 之前设置的,并且以后不会更改,则实际上根本不需要使用PropertyChanged通知,因为在绑定 ViewModel 时控件将看到预期的属性值.
  • 如果您绑定到一个属性,该属性的值将被初始分配或在设置为 ViewModel 后将更改,DataContextViewModel 必须继承自INotifyPropertyChanged并且属性设置器必须调用PropertyChanged事件,否则控件将永远不会知道属性值发生了变化。
  • 如果要将集合绑定到控件的ItemsSource属性,则需要考虑上述情况,但还需要考虑填充或更新集合内容的方式和时间。
  • 如果您正在创建和填充诸如列表之类的集合,然后设置 ViewModel 的属性(绑定到控件的ItemsSource属性)并且从不修改集合的内容(尽管您可以稍后将 ViewModel 属性分配给不同的集合),ViewModel 必须继承自INotifyPropertyChanged并且集合属性设置器必须调用该PropertyChanged事件。在这种情况下,您实际上不需要考虑 ObservableCollection;您可以在 ViewModel 中使用任何所需的集合类型。
  • 如果您在将集合绑定到控件的ItemsSource属性时修改集合的内容,则控件CollectionChanged需要事件才能正确更新;最简单的方法是ObservableCollection在你的 ViewModel 中使用;它会在添加或删除项目时自动引发CollectionChanged事件。

这些是有助于识别和解决使用绑定时最常见/最可能出现的问题的基本准则。

典型的属性绑定:

public class MyViewModel : INotifyPropertyChanged
{
    private string _myString;
    public string MyString
    {
        get => _myString;
        set
        {
            _myString = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(MyString));
        }
    }
}

在您的情况下,您可能只需ItemCollectionViewSourceSingole要从List<KeyFreq>to更改,ObservableCollection<KeyFreq>因为您在 ViewModel 构造函数中初始化了空集合,并且稍后才添加项目。


推荐阅读