代码之家  ›  专栏  ›  技术社区  ›  juharr

绑定itemssource并检查menuitem以获取WPF中可检查项的列表

  •  5
  • juharr  · 技术社区  · 15 年前

    我正在尝试设置 MenuItem 它将有一个可以选择的页码子菜单。我想把 ItemsSource 到页码列表(使用创建列表的转换器实际到pagecount),然后绑定 IsChecked 每个的属性 菜单项 在页面索引的子菜单中。我的问题是第二个绑定,因为它也需要一个转换器,但该转换器需要知道 菜单项 表示,但我无法确定如何将该信息传递给转换器。这是我迄今为止所做的尝试。

    <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 . 所以我的问题是,我如何才能传递我需要的信息,或者是否有其他的方法来做到这一点。

    注意:我已经试着把 菜单项 在A里面 ListBox 就绑定而言,它确实工作得很好,但导致子菜单以非标准方式工作。当你打开子菜单的时候 列表框 被视为一体 菜单项 .

    编辑

    这就是我到目前为止要做的。我试着和一个隐藏的 列表框 但当我把 MenuItem.ItemsSource 到“listbox.items”我得到了 int 而不是列表 ListBoxItem 这是我需要得到的 IsSelected 财产。所以我最终使用了Quartermeister的建议,即使用多重绑定来获取 ISCHECK 要绑定到的属性 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 代码

    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);
            }
        }
    }
    
    2 回复  |  直到 15 年前
        1
  •  3
  •   Quartermeister    15 年前

    你能用一个 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和convert将得到一个包含每个子绑定结果的数组。在本例中,它是一个两元素数组,其中第一个元素是当前输入pageindex,第二个索引是当前converterParameter、content。如果需要双向绑定,convertback将需要返回一个两元素数组,并且将返回 Binding.DoNothing 使其不尝试更新内容。

        2
  •  3
  •   Zamboni    15 年前

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