Привязка данных контекстного меню WPF - PullRequest
0 голосов
/ 14 декабря 2010

Я пытаюсь привязать контекстное меню (с флажком) вкладки к наблюдаемой коллекции. Когда пользователь проверяет или снимает отметку с пункта меню в первый раз, это состояние отражается в связанная переменная bool в необнаруживаемой коллекции. Но после этого это не отражается. Связывание в XAML выглядит следующим образом:

        <TabItem.ContextMenu>
            <ContextMenu Name="menu"
                         ItemsSource="{Binding Path=FieldNameCollection,Mode=TwoWay}"
                         ItemTemplate="{StaticResource SelectIndexFieldMenu}"></ContextMenu>
        </TabItem.ContextMenu>

Шаблон данных

        <DataTemplate x:Key="SelectIndexFieldMenu">
            <MenuItem Header="{Binding Path=IndexFieldName}"
                      IsCheckable="True"
                      IsChecked="{Binding Path=isIndexFieldSelected,Mode=TwoWay}"
                      IsEnabled="{Binding  Path=isCheckBoxEnabled}" />
        </DataTemplate>

(я не могу добавить фрагмент кода, поэтому я удалил '<' :() Класс для наблюдаемой коллекции является производным от NotifierBase. Еще одна вещь, которую я заметил, - если я проверяю источник ресурсов контекстного меню в view.xaml.cs в ContextMenuClosing, состояния корректно отражаются. </p>

1 Ответ

0 голосов
/ 15 декабря 2010

Непонятно, не увидев больше кода, что приводит к тому, что свойства не обновляются, но есть несколько проблем, которые могут способствовать.

Значения «isIndexFieldSelected» и «isCheckBoxEnabled» выглядят как имена полей, а не как свойства. Если это так, это может вызвать проблему, поскольку Binding требует свойств, но с учетом опубликованного кода, это не ясно.

То, как вы шаблонизируете элементы меню, приведет к созданию двух объектов MenuItem для каждого элемента коллекции. ContextMenu автоматически генерирует экземпляр MenuItem для каждого элемента в связанной коллекции ItemsSource, в которую вставляется шаблон DataTemplate для каждого элемента. Объявляя MenuItem внутри ItemTemplate, вы создаете MenuItem внутри раздела Header каждого MenuItem в ContextMenu. Это может быть тот случай, когда вы нажимаете и проверяете внешний элемент MenuItem, который не связан с данными. Попробуйте использовать эти ресурсы вместо шаблона и стиля MenuItems, которые сгенерированы для вас:

<DataTemplate x:Key="SelectIndexFieldMenuTemplate">
    <TextBlock Text="{Binding Path=IndexFieldName}"/>
</DataTemplate>

<Style x:Key="SelectIndexFieldMenuStyle" TargetType="{x:Type MenuItem}">
    <Setter Property="IsCheckable" Value="True" />
    <!--IsChecked is already TwoWay by default-->
    <Setter Property="IsChecked" Value="{Binding Path=isIndexFieldSelected}" />
    <Setter Property="IsEnabled" Value="{Binding  Path=isCheckBoxEnabled}" />
</Style>

И используйте их так:

<TabItem.ContextMenu>
    <!--TwoWay doesn't ever do anything on ItemsSource-->
    <ContextMenu Name="menu" ItemsSource="{Binding Path=FieldNameCollection}"
                 ItemContainerStyle="{StaticResource SelectIndexFieldMenuStyle}"
                 ItemTemplate="{StaticResource SelectIndexFieldMenuTemplate}"/>
</TabItem.ContextMenu>

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

private bool _isIndexFieldSelected;
public bool isIndexFieldSelected
{
    get { return _isIndexFieldSelected; }
    set
    {
        if (_isIndexFieldSelected == value)
            return;
        _isIndexFieldSelected = value;
        NotifyPropertyChanged("isIndexFieldSelected");
    }
}

public virtual void NotifyPropertyChanged(string propertyName)
{
    PropertyChangedEventArgs ea = new PropertyChangedEventArgs(propertyName);
    if (PropertyChanged != null)
        PropertyChanged(this, ea);
}

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