Флажки Treeview не обновляются после изменения привязанного свойства (SL4) - PullRequest
1 голос
/ 09 августа 2011

Моя проблема проста.У меня есть древовидное представление, привязанное к ObservableCollection объектов, и у всех этих объектов есть свои собственные ObservableCollections.Основываясь на выборе пользователем других критериев на моей странице, я хочу динамически установить, какие флажки отмечены. К сожалению, мои чекбоксы не могут обновить свой статус IsChecked после того, как я изменил соответствующее свойство bool, привязанное к IsChecked .Флажки будут в правильном состоянии при первом развертывании любого узла, но после этого они прекращают обновление.Я подозреваю, что это означает, что объекты не создаются / оцениваются, пока они не должны быть показаны в первый раз.

Структура данных Silverlight -> ViewModel -> ObservableCollection of StoreGroups LocalStoreGroups -> StoreGroup имеет ObservableCollectionStore Stores

Посредством отладки я заметил, что к этому не привязаны обработчики. 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 ]

2 голосов
/ 09 августа 2011

Похоже, вы обновляете свойство в ответ на событие загрузки.Вполне вероятно, что вы не участвуете в потоке пользовательского интерфейса при обновлении свойства.Если изменение не произойдет в потоке пользовательского интерфейса, оно не будет обновлять отображение.

Для связанных свойств и свойств, которые являются коллекциями (а не дочерними в наблюдаемых коллекциях), только OnPropertyChanged должен быть в потоке пользовательского интерфейса.,Свойства могут измениться раньше, но пользовательский интерфейс не изменит привязки, пока не будет вызван OnPropertyChanged.

Все наши ViewModels являются производными от созданной нами ViewModelBase, которая реализует вспомогательный метод SendPropertyChanged, как показано ниже (поэтому нам никогда не придется беспокоиться о перекрестномнарезания резьбы).

Все наши свойства notify вызывают это вместо непосредственного вызова OnPropertyChanged.

Он также предоставляет обычно полезный метод OnUiThread, чтобы вы могли выполнить произвольный код в потоке пользовательского интерфейса:

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);
    }
}
0 голосов
/ 12 августа 2011

В любом случае, раздача здесь должна была состоять в том, что никто не был подписан на событие PropertyChanged.Оказывается, что хотя я реализовал событие PropertyChanged, я забыл на самом деле дать классу интерфейс INotifyPropertyChanged.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...