INotifyPropertyChanged не работает с привязкой данных WPF - PullRequest
3 голосов
/ 12 октября 2011

У меня есть выпадающий список в моем файле MainWindow.xaml, например:

<ComboBox Name="material1ComboBox" 
          HorizontalAlignment="Center" 
          MinWidth="100" 
          ItemsSource="{Binding ViewProperties.MaterialDropDownValues}" 
          SelectedValue="{Binding ViewProperties.Material1SelectedValue}"
          SelectionChanged="Material1ComboBoxSelectionChanged">
 </ComboBox>

Я назначил текстовый текст в коде, используя this.datacontext = this.

Я создал ViewProperties доступ к нему осуществляется как свойство в MainWindow и является классом, который реализует INotifyPropertyChanged и содержит MaterialDropDownValues в качестве свойства.

Я даже изменил значение MaterialDropDownValues на ObservableCollection.

Проблема заключается в том, что привязка данных работает при инициализации, однако, если свойство MaterialDropDownValues изменяется, значения комбинированного списка не обновляются.

У меня есть следующее в классе ViewProperties:

    public ObservableCollection<string> MaterialDropDownValues 
    { 
        get { return this.materialDropDownValues; }
        set 
        { 
            this.materialDropDownValues = value;

            OnPropertyChanged("MaterialDropDownValues");
        } 
    }

    protected void OnPropertyChanged(string name)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(name));
        }
    }

Есть идеи, почему это не работает?Все остальные ответы, которые я мог найти, советовали реализовать INotifyPropertyChanged и сделать свойство наблюдаемой коллекцией.

Ответы [ 4 ]

1 голос
/ 12 октября 2011

Решение 1:

Не воссоздай this.materialDropDownValues попробуй сделать

 this.materialDropDownValues.Clear();
 foreach(var mystring in myStrings) 
       this.materialDropDownValues.Add(mystring);

для всех новых предметов. Если это не помогает, попробуйте решение 2 ...

Решение 2:

Согласно моему опыту, ObservableCollection примитивных типов, таких как int, string, bool, double и т. Д., Не обновляется в уведомлении об изменении свойства, если ItemsControl.ItemTemplate не указано.

   <ComboBox Name="material1ComboBox"
             HorizontalAlignment="Center"
             MinWidth="100"
             ItemsSource="{Binding ViewProperties.MaterialDropDownValues}"
             SelectedValue="{Binding ViewProperties.Material1SelectedValue}"
             SelectionChanged="Material1ComboBoxSelectionChanged">
         <ComboBox.ItemTemplate>
             <DataTemplate DataType="{x:Type System:String}">
                 <TextBlock Text="{Binding}" />
             </DataTemplate> 
         </ComboBox.ItemTemplate>
    </ComboBox>

Это связано с тем, что контейнер элементов itemscontrol создает в нем ненаблюдаемые контейнеры элементов для примитивных данных путем простого копирования item.ToString (). В приведенном выше коде {Binding} должен обновлять изменения данных при изменении всего источника элементов.

Дайте мне знать, если это работает.

0 голосов
/ 12 октября 2011

Редактировать в ответ на комментарии

Ни один из нижеприведенных вопросов не решил проблему, но оставлен в качестве ссылки.


Исходный ответ

Проблема в том, что вы не указали DataContext для своего представления, в котором WPF ищет значения Binding с помощьюпо умолчанию.

При условии, что ваше свойство ViewProperties в MainWindow является общедоступным, вы можете просто изменить привязку на:

ItemsSource="{Binding ViewProperties.MaterialDropDownValues, 
    RelativeSource={RelativeSource FindAncestor, AncestorType=Window}"

Это заставит WPF искать значение свойства в первом

В качестве альтернативы вы можете просто установить для свойства Window.DataContext свой экземпляр ViewProperties и изменить привязку следующим образом:

ItemsSource="{Binding MaterialDropDownValues}"

Любой из них будет работать, но я бы предложил использовать последний, так как он ближе к шаблону MVVM, который обычно предпочитается в приложениях WPF / XAML.

0 голосов
/ 12 октября 2011

что произойдет, если вы измените свой xaml на

<ComboBox Name="material1ComboBox" 
      HorizontalAlignment="Center" 
      MinWidth="100" 
      DataContext="{Binding ViewProperties}"
      ItemsSource="{Binding MaterialDropDownValues}" 
      SelectedValue="{Binding Material1SelectedValue}"
      SelectionChanged="Material1ComboBoxSelectionChanged">
</ComboBox>

, тем не менее, вы должны просто создать экземпляр своей коллекции один раз и просто использовать удаление, добавление и очистку при использовании OberservableCollection.

0 голосов
/ 12 октября 2011

Когда я сталкиваюсь с такими вещами, первое, что я делаю, это играю в режиме привязки. Что-то вроде:

 ItemsSource="{Binding Path=ViewProperties.MaterialDropDownValues, Mode=TwoWay}"

Это иногда сбивает вас с толку. Еще одна вещь, в которой я бы позаботился, это то, что если вы создаете экземпляры новых объектов ViewProperties после вашей первоначальной загрузки, вы уведомляете об этом изменения. Если вы этого не сделаете, XAML будет ссылаться на устаревшую версию объекта, в то время как модель кода / представления работает на другой версии.

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