Silverlight 绑定属性更改后未更新Treeview复选框(SL4)
我的问题很简单。我有一个树状视图绑定到一个对象的可观察集合,这些对象都有自己的可观察集合。根据用户在我的页面上选择的其他条件,我希望动态设置选中的复选框不幸的是,在我更改绑定到IsChecked的相应bool属性后,我的复选框无法更新其IsChecked状态。第一次展开任何节点时,复选框将处于正确状态,但之后它们将停止更新。我怀疑这意味着在第一次实际显示对象之前,不会创建/评估对象 数据结构为Silverlight->ViewModel->ObservableCollection of StoreGroups LocalStoreGroups->StoreGroup has ObservableCollection of Store Stores 通过调试,我注意到没有附加到this.PropertyChanged的处理程序,我想知道这是否是问题所在 Treeview控件:Silverlight 绑定属性更改后未更新Treeview复选框(SL4),silverlight,checkbox,treeview,Silverlight,Checkbox,Treeview,我的问题很简单。我有一个树状视图绑定到一个对象的可观察集合,这些对象都有自己的可观察集合。根据用户在我的页面上选择的其他条件,我希望动态设置选中的复选框不幸的是,在我更改绑定到IsChecked的相应bool属性后,我的复选框无法更新其IsChecked状态。第一次展开任何节点时,复选框将处于正确状态,但之后它们将停止更新。我怀疑这意味着在第一次实际显示对象之前,不会创建/评估对象 数据结构为Silverlight->ViewModel->ObservableCollection of Stor
<controls:TreeView ItemsSource="{Binding LocalStoreGroups}" ItemTemplate="{StaticResource TreeviewStoreGroupTemplate}" />
选择更改代码
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;
}
看起来您正在更新属性以响应加载事件。更新属性时,很可能您不在UI线程上。除非在UI线程上发生更改,否则不会更新显示 对于绑定属性和集合属性(而不是可观察集合中的子级),只有OnPropertyChanged需要位于UI线程上。属性可以提前更改,但在调用OnPropertyChanged之前,UI不会更改绑定 我们所有的ViewModels都源自我们创建的ViewModelBase,它实现了一个帮助器SendPropertyChanged,如下所示(因此我们永远不必担心跨线程) 我们所有的notify属性都调用它,而不是直接调用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);
}
}
无论如何,这里的泄露应该是没有人订阅PropertyChanged事件。事实证明,尽管我实现了PropertyChanged事件,但我忘记了实际为类提供INotifyPropertyChanged接口 设置该值时,是否在后台线程中发生此情况?否,在UI线程上使用以下方法调用底部的代码(要更改的代码为Selected):来自Mvvmlight的DispatcherHelper.CheckBeginInvokeOnUI(…)。我想知道
OnPropertyChanged
方法如何工作,因为它不接受字符串,虽然您向它传递一个字符串,但在这两者之间有一个我没有复制的方法,该方法创建了参数,然后将它们传递给我复制的参数。无论如何,这里给出的信息应该是没有人订阅PropertyChanged事件。事实证明,尽管我实现了PropertyChanged事件,但我忘记了实际为类提供INotifyPropertyChanged接口。通过在visual studio中使用断点进行调查,我可以确认在主线程上调用了更新代码。此外,我正在使用MVVMLight框架,它确实提供了一种方法来实现您的建议(尽管您的解决方案看起来更整洁)。最后,属性更改事件将永远不会在试图发出更改信号的对象上引发,因为this.PropertyChanged=null。这可能是因为它是可观察集合中某个对象的子对象吗?
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;
}
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);
}
}