Свойство WPF для привязки данных IsEnabled - PullRequest
2 голосов
/ 11 февраля 2009

Итак, я сейчас изучаю WPF и хочу сделать простую привязку данных между значением bool и тем, включен или нет MenuItem или нет.

Я закодировал это так:

<MenuItem Name="miSaveFile" Header="Save" Click="miSaveFile_Click"
IsEnabled="{Binding}" />

И в файле .cs я установил:

miSaveFile.DataContext = dataChanged;

По какой-то причине MenuItem не отражает должным образом состояние dataChanged.

Чего мне не хватает?

Ответы [ 3 ]

4 голосов
/ 11 февраля 2009

Вы лучше привязываетесь к объекту, чем к примитивному типу. Этот объект часто называют «моделью» для вашего представления.

WPF использует интерфейс INotifyPropertyChanged для модели (или часто модели представления), чтобы уведомить представление о том, что модель изменила состояния.

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

Когда вы устанавливаете привязку, вам нужно беспокоиться о 5 основных элементах привязки. Привязка имеет исходный объект, исходный путь к исходному объекту, целевой объект, целевое свойство для целевого объекта и необязательный преобразователь.

Если вы не укажете источник, по умолчанию используется DataContext элемента управления, для которого установлена ​​привязка. Существуют и другие варианты настройки источника. Здесь - статья Microsoft по настройке источника. Затем вы можете установить путь свойства, чтобы извлечь из источника для привязки. В вашем случае источником является логическое значение, и нет пути, потому что для привязки используется весь исходный объект.

Цель - это всегда элемент управления, для которого вы устанавливаете привязку, а свойство target - это свойство этого элемента управления, к которому вы привязываете. В этом случае MenuItem и IsEnabled.

Конвертер может при желании преобразовать исходное значение в значение, совместимое с целевым свойством. Вы можете использовать любой объект для конвертера, который реализует IValueConverter или IMultiValueConverter (для MutliBindings).

В вашем случае я сначала создал бы модель, которая реализует INotifyPropertyChanged. Затем я бы назначил DataContext меню для экземпляра модели. Тогда я бы установил привязку к:

IsEnabled="{Binding Path=EnableFlag}"

(где EnableFlag - логическое свойство в модели, с которой вы хотите связать меню)

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

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

Для MenuItem, не лучше ли использовать модель Command, а не свойства Click и IsEnabled?

После InitialiseComponent ():

this.CommandBindings.Add(new CommandBinding(ApplicationCommands.Save, fileSaveExecuted, fileSaveCanExecute));

Дополнительные методы:

/* here is where you set e.CanExecute true for enabled: */
    private void fileSaveCanExecute(object x, CanExecuteRoutedCommandEventArgs e)) { e.CanExecute = ...; e.Handled = true; }
/* here is where you act on the command: */
    private void fileSaveExecuted(object sender, ExecutedRoutedEventArgs e) { ... }

XAML:

<MenuItem Header="_Save" Command="Save"/>
1 голос
/ 11 февраля 2009

Как пользовательский интерфейс узнает, когда переменная dataChanged действительно изменилась?

Обычно я связываюсь со свойством объекта и позволяю этому классу реализовать INotifyPropertyChanged. Пользовательский интерфейс затем «автоматически» обновляется всякий раз, когда вызывается событие PropertyChanged.

Так что я бы

<MenuItem Name="miSaveFile" Header="Save" Click="miSaveFile_Click"
IsEnabled="{Binding DataChanged}"</MenuItem>

и затем установите miSaveFile.DataContext = myObject.DataChanged (myObject может быть таким, если вы используете код позади)

Редактировать: я только что сделал быстрый тест. Если вы устанавливаете контекст данных непосредственно на свойство DataChanged, подписка на событие PropertyChanged объекта-владельца не добавляется. Но решение, которое я предлагаю, работает.

...