c# - 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 并查看项目。但它们不会出现在数据网格中。有什么建议吗?
解决方案
使用绑定时要注意的一个关键点是控件不会从绑定的属性中更新,除非并且直到它被通知值已更改。实现此通知有两种基本方法:
继承您的 ViewModel并在您的属性值更改时
INotifyPropertyChanged
调用该事件。PropertyChanged
这种方法适用于大多数情况,包括绑定到控件的数字和字符串属性,例如TextBlock
和TextBox
。用于
ObservableCollection
绑定到ItemsSource
属性的集合(用于具有ItemsSource
属性的控件)。
控件知道INotifyPropertyChanged
接口和INotifyCollectionChanged
底层接口ObservableCollection
,并监听相应的PropertyChanged
事件CollectionChanged
。
选择适当技术的指南如下:
- 如果 ViewModel 中的属性值是在控件
DataContext
设置为 ViewModel 之前设置的,并且以后不会更改,则实际上根本不需要使用PropertyChanged
通知,因为在绑定 ViewModel 时控件将看到预期的属性值. - 如果您绑定到一个属性,该属性的值将被初始分配或在设置为 ViewModel 后将更改,则
DataContext
ViewModel 必须继承自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 构造函数中初始化了空集合,并且稍后才添加项目。
推荐阅读
- c# - 实体框架与托管标识的 Azure SQL 数据库发生连接错误
- c# - 使用 Marshal 类时代码未执行的问题
- android - Gradle 插件 3.5.0:“无法转换工件”、“JetifyTransform 执行失败”
- javascript - 检查文件或模块是否已导入
- node.js - 为什么在运行 react-native 运行后,说我“无法解析模块”+ lerna
- java - 用于检查 VM 是否崩溃的 Powershell 脚本
- python - Tokenizer 扩展提取
- android - 我想从 android 应用程序的 firebase 中检索用户数据及其值?
- ios - 我想在我的应用程序中购买电子书。我可以通过 webview 付款而不使用应用内购买吗.. iTunes 商店是否批准了我的应用
- javascript - 非法调用方法分配