绑定属性更改后树视图复选框不更新(SL4)

时间:2011-08-09 17:37:27

标签: silverlight checkbox treeview

我的问题很简单。我有一个绑定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;
        }

2 个答案:

答案 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接口。