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

juh*_*arr 5 c# wpf binding menuitem

我正在尝试设置一个MenuItem可以选择的页码子菜单.我想绑定ItemsSource到一个页码列表(实际上是一个创建列表的转换器的PageCount),然后将子菜单IsChecked中每个页面的属性绑定MenuItem到PageIndex.我的问题是第二个绑定,因为它也需要转换器,但转换器需要知道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>
Run Code Online (Sandbox Code Playgroud)

当然问题是ConverterParameter不能绑定,因为它不是一个DependencyProperty.所以我的问题是我如何传递我需要的信息,或者有另一种方法来做到这一点.

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

编辑

所以这就是我到目前为止所做的工作.我尝试绑定到隐藏ListBox但是当我绑定MenuItem.ItemsSource到'ListBox.Items'时,我得到了ints 的列表而不是ListBoxItem我需要获取IsSelected属性的s 列表.所以我最终使用了Quartermeister的建议,即使用MultiBinding将IsChecked属性绑定到PageIndexin 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>
Run Code Online (Sandbox Code Playgroud)

这是GotoPageMenuItem_Click代码

private void GotoPageMenuItem_Click(object sender, RoutedEventArgs e)
{
    var item = sender as MenuItem;
    if (item != null)
    {
        //If the item is already checked then we don't need to do anything
        if (!item.IsChecked)
        {
            var pageNum = (int)item.Header;
            CurrentImage.PageIndex = (pageNum - 1);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Zam*_*oni 5

听起来您正在尝试构建动态菜单来控制每个菜单项的选中状态。
我扩展了我编写的一些代码,以使用 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>
Run Code Online (Sandbox Code Playgroud)

这是视图模型:

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;
  }
}
Run Code Online (Sandbox Code Playgroud)

这是保存命令的类:

  public class MyCommand
  {
     public ICommand Command { get; set; }
     public string Text { get; set; }
     public string Parameter { get; set; }
     public Boolean Checked { get; set; }
  }
Run Code Online (Sandbox Code Playgroud)


Qua*_*ter 4

您可以使用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>
Run Code Online (Sandbox Code Playgroud)

让您的pageNumChecked转换器实现IMultiValueConverter而不是 IValueConverter,Convert 将获得一个包含每个子绑定结果的数组。在本例中,它将是一个双元素数组,其中第一个元素是当前输入 PageIndex,第二个索引是当前 ConverterParameter Content。如果您想要双向绑定,ConvertBack 将需要返回一个双元素数组,并且您将返回Binding.DoNothing第二个参数,以便它不会尝试更新 Content。