绑定MenuItem的ItemsSource和IsChecked以获取WPF中可检查项的列表

时间:2010-06-24 21:22:23

标签: c# wpf binding menuitem

我正在尝试设置MenuItem,其中包含可以选择的页码子菜单。我想将ItemsSource绑定到页码列表(实际上是使用转换器创建列表的PageCount),然后在子菜单中绑定每个IsChecked的{​​{1}}属性到PageIndex。我的问题是第二个绑定,因为它也需要转换器,但转换器需要知道MenuItem表示的页码,但我无法弄清楚如何将该信息传递给转换器。这是我到目前为止所尝试的内容。

MenuItem

当然问题是<MenuItem Header="_Goto Page" ItemsSource="{Binding Path=CurrentImage.PageCount, Converter={StaticResource countToList}}"> <MenuItem.ItemContainerStyle> <Style TargetType="MenuItem"> <Setter Property="IsCheckable" Value="True"/> <Setter Property="IsChecked" Value="{Binding ElementName=MainWindow, Path=CurrentImage.PageIndex, Mode=TwoWay, Converter={StaticResource pageNumChecked}, ConverterParameter={Binding RelativeSource={RelativeSource Self}, Path=Content}}"/> </Style> </MenuItem.ItemContainerStyle> </MenuItem> 无法绑定,因为它不是ConverterParameter。所以我的问题是我如何传递我需要的信息,或者有另一种方法来做到这一点。

注意:我已经尝试将DependencyProperty置于MenuItem内部,就绑定而言,它的效果非常好,但导致子菜单以非标准方式运行。也就是说,当您打开子菜单时,整个ListBox被视为一个ListBox

修改

所以这就是我到目前为止所做的工作。我尝试绑定到隐藏的MenuItem但是当我将ListBox绑定到'ListBox.Items'时,我得到了MenuItem.ItemsSource的列表而不是int的列表我需要获得ListBoxItem属性。所以我最终使用了Quartermeister的建议,即使用MultiBinding将IsSelected属性绑定到IsChecked模式下的PageIndex。为了处理另一个方向,我在OneWay事件上使用了一个事件处理程序。值得注意的是,起初我将Click设置为IsCheckable并且正在处理true事件,但结果却是一些奇怪的行为。

Checked

这是<MenuItem x:Name="GotoPageMenuItem" Header="_Goto Page" ItemsSource="{Binding Path=CurrentImage.PageCount, Converter={StaticResource countToList}}"> <MenuItem.ItemContainerStyle> <Style TargetType="MenuItem"> <Setter Property="IsCheckable" Value="False"/> <EventSetter Event="Click" Handler="GotoPageMenuItem_Click"/> <Setter Property="IsChecked"> <Setter.Value> <MultiBinding Converter="{StaticResource pageNumChecked}" Mode="OneWay"> <Binding RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type Window}}" Path="CurrentImage.PageIndex" Mode="OneWay"/> <Binding RelativeSource="{RelativeSource Self}" Path="Header" Mode="OneWay"/> </MultiBinding> </Setter.Value> </Setter> </Style> </MenuItem.ItemContainerStyle> </MenuItem> 代码

GotoPageMenuItem_Click

2 个答案:

答案 0 :(得分:3)

你能用MultiBinding做你想做的事吗?

<Setter Property="IsChecked">
    <Setter.Value>
        <MultiBinding Converter="{StaticResource pageNumChecked}">
            <Binding ElementName="MainWindow" Path="CurrentImage.PageIndex" Mode="TwoWay"/>
            <Binding RelativeSource="{RelativeSource Self}" Path="Content"/>
        </MultiBinding>
    </Setter.Value>
</Setter>

让你的pageNumChecked转换器实现IMultiValueConverter而不是IValueConverter,转换将得到一个数组,其中包含每个子绑定的结果。在这种情况下,它将是一个双元素数组,其中第一个元素是您当前的输入,PageIndex,第二个索引是您当前的ConverterParameter,Content。如果你想要双向绑定,ConvertBack将需要返回一个双元素数组,你将为第二个参数返回Binding.DoNothing,这样它就不会尝试更新内容。

答案 1 :(得分:3)

听起来您正在尝试构建控制每个菜单项的已检查状态的动态菜单 我扩展了一些我编写的代码,用MVVM模式在WPF中构建动态菜单,并添加了检查逻辑。

这是XAML:

<Menu DockPanel.Dock="Top">
    <MenuItem ItemsSource="{Binding Commands}"
              Header="_Item Container Style">
        <MenuItem.ItemContainerStyle>
            <Style TargetType="{x:Type MenuItem}">
                <Setter Property="IsCheckable" Value="True"/>
                <Setter Property="IsChecked"  Value="{Binding Path=Checked}"/>
                <Setter Property="Header" Value="{Binding Path=Text}" />
                <Setter Property="Command" Value="{Binding Path=Command}" />
                <Setter Property="CommandParameter" Value="{Binding Path=Parameter}" />
            </Style>
        </MenuItem.ItemContainerStyle>
    </MenuItem>
</Menu>

以下是视图模型:

public class MainViewModel : ViewModelBase
{
  public MainViewModel()
  {
     GoCommand = new DelegateCommand<object>(OnGoCommand, CanGoCommand);
     LoadCommands();
  }

  private List<MyCommand> _commands = new List<MyCommand>();
  public List<MyCommand> Commands
  {
     get { return _commands; }
  }

  private void LoadCommands()
  {
     MyCommand c1 = new MyCommand { Command = GoCommand, Parameter = "1", Text = "Menu1", Checked = true};
     MyCommand c2 = new MyCommand { Command = GoCommand, Parameter = "2", Text = "Menu2", Checked = true };
     MyCommand c3 = new MyCommand { Command = GoCommand, Parameter = "3", Text = "Menu3", Checked = false };
     MyCommand c4 = new MyCommand { Command = GoCommand, Parameter = "4", Text = "Menu4", Checked = true };
     MyCommand c5 = new MyCommand { Command = GoCommand, Parameter = "5", Text = "Menu5", Checked = false };
     _commands.Add(c1);
     _commands.Add(c2);
     _commands.Add(c3);
     _commands.Add(c4);
     _commands.Add(c5);
  }

  public ICommand GoCommand { get; private set; }
  private void OnGoCommand(object obj)
  {
  }

  private bool CanGoCommand(object obj)
  {
     return true;
  }
}

这是包含命令的类:

  public class MyCommand
  {
     public ICommand Command { get; set; }
     public string Text { get; set; }
     public string Parameter { get; set; }
     public Boolean Checked { get; set; }
  }