2

我在我的项目中使用这个 ObservableCollection-Class: Link
I want to Bind a RibbonMenuButton to a 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

4 回答 4

3

这不起作用,因为您的字典不被视为字典,而是被视为IEnumerable<KeyValuePair<string, bool>>. 因此,每个RibbonMenuItem都绑定到KeyValuePair<string, bool>具有只读属性的 aKeyValue.
你可以做一件事s

1. 使用 anObservableCollection<Tuple<string, bool>>代替字典并绑定IsCheckedItem2.
2. 创建一个包含IsChecked属性的小助手类,并更改您的字典以包含该类作为值并绑定IsCheckedValue.IsChecked.

我会选择答案二,因为所需的更改和可能的副作用较小。
我的回答假设您希望在IsChecked. 如果没有,请选择 slugster 的答案。

于 2011-05-17T11:39:38.817 回答
1

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 Data Binding: Part 1(具体查看页面底部附近的Binding Mode部分)

于 2011-05-17T11:39:49.350 回答
1

如果您想在不使用辅助类的情况下进行绑定MenuItemsDictionary<string, bool>就像接受的答案所暗示的那样,这是最小更改的解决方案(无需添加任何其他内容):

  • 在 who 中定义一个Click事件,该事件ItemContainerStyleClickEventHandler更新字典。
  • 声明一个字典并在用户控件/窗口的构造函数中初始化它

在代码中:

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

就是这样!你都准备好了!

归功于slugster和他对 OneWay 绑定的 XAML 代码的回答 :)

于 2017-06-14T10:21:25.920 回答
0

作为绑定到字典的这个问题的一般解决方案,我创建了一个 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;
         }
      }
    }
于 2014-04-07T15:12:12.417 回答