WPF: привязка к (наблюдаемому) словарю - PullRequest
2 голосов
/ 17 мая 2011

Я использую этот класс ObservableCollection в своем проекте: Ссылка Я хочу привязать RibbonMenuButton к ObservableDictionary<string,bool>:

<r:RibbonMenuButton ItemsSource="{Binding MyDictionary}">
    <r:RibbonMenuButton.ItemContainerStyle>
        <Style TargetType="{x:Type r:RibbonMenuItem}">
            <Setter Property="IsCheckable" Value="true"/>
            <Setter Property="Header" Value="{Binding Path=Key}"/>
            <Setter Property="IsChecked" Value="{Binding Path=Value}"/>
        </style>
    </r:RibbonMenuButton.ItemContainerStyle>
</r:RibbonMenuButton>

Но я получаю исключения, поскольку свойства-значения внутренних IDictionary-KeyValuePairs доступны только для чтения.Любая идея, как решить эту проблему?Я думал о чем-то вроде:

<Setter Property="IsChecked" Value="{Binding Source=MyDictionary[{Binding Path=Key}]}"/>

Но это не сработает, потому что {Binding} в {Binding} ...

Ответы [ 4 ]

3 голосов
/ 17 мая 2011

Это не работает, потому что ваш словарь рассматривается не как словарь, а как IEnumerable<KeyValuePair<string, bool>>.Таким образом, каждый RibbonMenuItem связан с KeyValuePair<string, bool> со свойствами только для чтения Key и Value.
. Вы можете сделать два одно s :

1. Используйте ObservableCollection<Tuple<string, bool>> вместо словаря и привяжите IsChecked к Item2.
2. Создайте небольшой вспомогательный класс, содержащий свойство IsChecked, и измените ваш словарьчтобы содержать этот класс в качестве значения и связать IsChecked с Value.IsChecked.

Я бы пошел с ответом два, потому что необходимые изменения и возможные побочные эффекты меньше.
Мой ответ предполагает, что вы хотитеиметь двухстороннюю привязку IsChecked.Если нет, воспользуйтесь ответом Слагстера.

1 голос
/ 14 июня 2017

Если вы хотите связать MenuItems с Dictionary<string, bool> без использования вспомогательного класса, как предлагает принятый ответ, вот решение минимальное изменение (не нужно ничего добавлять):

  • определяет событие Click внутри ItemContainerStyle, чье ClickEventHandler обновит диктитон.
  • объявляет словарь и инициализирует его в конструкторе UserControl / Window

В коде:

MainWindow.xaml:

<MenuItem Header="_My settings" ItemsSource="{Binding MySettings}">
    <MenuItem.ItemContainerStyle>
      <Style TargetType="{x:Type MenuItem}">
        <Setter Property="IsCheckable" Value="true"/>
        <Setter Property="Header" Value="{Binding Key, Mode=OneWay}"/>
        <Setter Property="IsChecked" Value="{Binding Value, Mode=OneWay}"/>
        <!-- this is the main line of code -->
        <EventSetter Event="Click" Handler="MySettings_ItemClick"/>
      </Style>
    </MenuItem.ItemContainerStyle>
</MenuItem>

MainWindow.xaml.cs:

public partial class MainWindow : Window
{
    // properties...

    // Declaration of the dictionary
    public Dictionary<string, bool> MySettings{ get; set; }

    public MainWindow()
    {
        InitializeComponent();
        // Initialize the dictionary
        MySettings = new Dictionary<string, bool>()
        {
            { "SettingOne", true}
            // Other pairs..
        };
    }
    // other things..

    // ClickEvent hanlder
    private void MySettings_ItemClick(object sender, RoutedEventArgs e)
    {
        MenuItem clickedItem = (sender as MenuItem);
        MySettings[clickedItem.Header as string] = clickedItem.IsChecked;
    }
} // end of MainWindow class

Вот и все!Все готово!

Кредиты для Слагстера и его ответ для кода XAML для привязки OneWay:)

1 голос
/ 17 мая 2011

Связывание WPF является двусторонним по умолчанию.Сделайте его односторонним и посмотрите, решит ли это вашу проблему.

<r:RibbonMenuButton ItemsSource="{Binding MyDictionary}">
    <r:RibbonMenuButton.ItemContainerStyle>
        <Style TargetType="{x:Type r:RibbonMenuItem}">
            <Setter Property="IsCheckable" Value="true"/>
            <Setter Property="Header" Value="{Binding Key, Mode=OneWay}"/>
            <Setter Property="IsChecked" Value="{Binding Value, Mode=OneWay}"/>
        </style>
    </r:RibbonMenuButton.ItemContainerStyle>
</r:RibbonMenuButton>

Вот вам справка: Привязка данных MSDN Windows Presentation Foundation: Часть 1 (см. Раздел Режим переплета близко к нижней части страницы)

0 голосов
/ 07 апреля 2014

В качестве общего решения этой проблемы привязки к словарям я создал UpdateableKeyValuePair и возвращаю его вместо обычного KeyValuePair. Вот мой класс:

   public class UpdateableKeyValuePair<TKey,TValue>
      {
      private IDictionary<TKey, TValue> _owner;
      private TKey _key;
      public UpdateableKeyValuePair(IDictionary<TKey, TValue> Owner, TKey Key_)
         {
         _owner = Owner;
         _key = Key_;
         }

      public TKey Key
         {
         get
            {
            return _key;
            }
         }

      public TValue Value
        {
        get
          {
          return _owner[_key];
          }
       set
         {
          _owner[_key] = value;
         }
      }
    }
...