我的问题很简单。我有一个绑定ObservableCollection对象的树视图,这些对象都有自己的ObservableCollections。根据用户对我页面上其他条件的选择,我想动态设置选中的复选框。 不幸的是,在我更改了绑定到IsChecked 的相应bool属性后,我的复选框无法更新其IsChecked状态。第一次扩展任何节点时,复选框将处于正确的状态,但之后它们将停止更新。我怀疑这意味着在第一次显示对象之前,不会创建/评估对象。
数据结构是Silverlight - > ViewModel - > ObservableCollection of StoreGroups LocalStoreGroups - > StoreGroup具有商店商店的ObservableCollection
通过调试我注意到没有处理程序附加到this.PropertyChanged,我想知道这是否是问题?
Treeview控件:
<controls:TreeView ItemsSource="{Binding LocalStoreGroups}" ItemTemplate="{StaticResource TreeviewStoreGroupTemplate}" />
在我的项目中,我使用了一个带有以下HeirarchalDataTemplates的树视图:
<UserControl.Resources>
<sdk:HierarchicalDataTemplate x:Key="TreeviewStoreTemplate">
<CheckBox IsChecked="{Binding IsSelected, Mode=TwoWay}" Content="{Binding DTO.Name}" />
</sdk:HierarchicalDataTemplate>
<sdk:HierarchicalDataTemplate x:Key="TreeviewStoreGroupTemplate" ItemsSource="{Binding Stores}" ItemTemplate="{StaticResource TreeviewStoreTemplate}">
<CheckBox IsChecked="{Binding IsSelected, Mode=TwoWay}" Content="{Binding DTO.Name}" />
</sdk:HierarchicalDataTemplate>
</UserControl.Resources>
IsSelected属性的代码(StoreGroup对象和Store对象都具有此属性:
private bool _IsSelected;
public bool IsSelected
{
get { return _IsSelected; }
set
{
_IsSelected = value;
OnPropertyChanged("IsSelected");
}
}
protected void OnPropertyChanged(PropertyChangedEventArgs e)
{
PropertyChangedEventHandler temp = this.PropertyChanged;
if (null != temp)
temp(this, e);
}
更改IsSelected的代码
foreach (Store s in LocalStoreGroups.SelectMany(sg => sg.Stores))
{
s.IsSelected = false;
}
foreach (StoreLink link in links)
{
Store targetStore = (from s in LocalStoreGroups.SelectMany(sg => sg.Stores) where s.DTO.ID == link.DTO.StoreID select s).FirstOrDefault();
targetStore.IsSelected = true;
}
答案 0 :(得分:2)
看起来您正在更新属性以响应load事件。当您更新属性时,很可能您不在UI线程上。除非在UI线程上发生更改,否则它不会更新显示。
对于作为集合的绑定属性和属性(而不是可观察集合中的子节点),只有OnPropertyChanged需要位于UI线程上。属性可以更早更改,但在调用OnPropertyChanged之前,UI不会更改绑定。
我们所有的ViewModel派生自我们创建的ViewModelBase,它实现了如下所示的助手SendPropertyChanged(所以我们永远不必担心跨线程)。
我们所有的通知属性都会调用它而不是直接调用OnPropertyChanged。
它还公开了一个通常有用的OnUiThread方法,因此您可以在UI线程上执行任意代码:
protected delegate void OnUiThreadDelegate();
public event PropertyChangedEventHandler PropertyChanged;
public void SendPropertyChanged(string propertyName)
{
if (this.PropertyChanged != null)
{
this.OnUiThread(() => this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName)));
}
}
protected void OnUiThread(OnUiThreadDelegate onUiThreadDelegate)
{
if (Deployment.Current.Dispatcher.CheckAccess())
{
onUiThreadDelegate();
}
else
{
Deployment.Current.Dispatcher.BeginInvoke(onUiThreadDelegate);
}
}
答案 1 :(得分:0)
无论如何,这里的赠品应该是没有人订阅PropertyChanged事件。事实证明,虽然我实现了PropertyChanged事件,但我忘了实际给类提供了INotifyPropertyChanged接口。