2011-05-17 50 views
2

我用我的计划之内这个的ObservableCollection级:Link
我想绑定RibbonMenuButton到ObservableDictionary<string,bool>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 Path=Key}"/> 
      <Setter Property="IsChecked" Value="{Binding Path=Value}"/> 
     </style> 
    </r:RibbonMenuButton.ItemContainerStyle> 
</r:RibbonMenuButton> 

,但我得到的例外,因为内部IDictionary-KeyValuePairs的Value-Properties属性是只读的。任何想法如何解决这个问题?

我想过是这样的:

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

但是这是不行的“{}绑定在{结合}的原因...

回答

3

这是不行的,因为你的字典ISN不被视为字典,而是作为IEnumerable<KeyValuePair<string, bool>>。因此,每个RibbonMenuItem都绑定到KeyValuePair<string, bool>,只读属性KeyValue
你可以做一件事小号

1.使用ObservableCollection<Tuple<string, bool>>而不是字典,并结合IsCheckedItem2
2.创建一个包含IsChecked属性的小助手类,并更改字典以将该类包含为值并将IsChecked绑定到Value.IsChecked

我会与答案二,因为所需的变化和可能的副作用较小。
我的答案假定您想在IsChecked上有双向绑定。如果没有,请与slugster的答案一起。

+0

元组......这就是我正在寻找的类,工程PERFEKT我! – Reini 2011-05-17 11:51:06

+0

narf ... Touple.Item1/2也是只读的。所以我打算用辅助班,努力避免这种... – Reini 2011-05-17 11:58:21

+0

@Reini:哎呀。对不起...... – 2011-05-17 11:59:19

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(专门检查绑定模式靠近页的底部的部分

+0

将无法​​正常工作......我想将复选框的IsChecked状态反映到我的ViewModel;) – Reini 2011-05-17 11:51:51

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; 
     } 
     } 
    } 
1

如果你要绑定MenuItemsDictionary<string, bool>不使用辅助类,如接受的答案表明,这里是微小病变解决方案(无需添加任何其他内容):

  • 定义ItemContainerStyleClickEventHandlerClick事件将更新dicitonary。
  • 声明字典和初始化UserControl的/窗的构造

在代码中:

主窗口。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 and his answer为单向XAML代码结合:)