【问题标题】:WPF: Contextmenu MenuItem with static and dynamic entries and Command bindingWPF:具有静态和动态条目以及命令绑定的 Contextmenu MenuItem
【发布时间】:2021-02-27 13:56:25
【问题描述】:

我有一个包含菜单项的上下文菜单。到目前为止,一切都很好。 在子菜单(“颜色”)中,我想要静态条目(“重置颜色”和“自定义颜色”)以及动态值。它目前看起来像这样: Contextmenu.

所以,我的问题是:

我需要做什么才能获得相同的样式:静态和动态(通过我的 CustomColorCollection)条目,并且仍然可以单独设置 Command 和 CommandParameter?

动态值绑定到 public static ObservableCollection<ContextMenuColor> ColorList { get; set; } = new ObservableCollection<ContextMenuColor>() ContextMenuColor 是一个像这样的小类:

    public class ContextMenuColor
    {
        public string Title { get; set; }
        public string Color { get; set; }
        public ContextMenuColor(string title, string color)
        {
            this.Title = title;
            this.Color = color;
        }
    }

当我点击一个菜单项时,我希望它以 ContextMenuColor.Color 作为命令参数来运行我的 ICommand SetColorCommand。

这是我目前在 XAML 中的内容:

<MenuItem Header="Colors">
    <MenuItem.Resources>
        <CollectionViewSource x:Key="CustomColorCollection" Source="{Binding ColorList}"/>
    </MenuItem.Resources>
    <MenuItem.ItemsSource>
        <CompositeCollection>
            <MenuItem Header="Reset color" Command="{Binding SetColorCommand}" CommandParameter="#DCDCDC" UsesItemContainerTemplate="False">
                <MenuItem.Icon>
                    <Rectangle Width="20" Height="20" Fill="#DCDCDC"/>
                </MenuItem.Icon>
            </MenuItem>
            <MenuItem Header="Custom color" Command="{Binding SetColorCommand}" CommandParameter="custom" UsesItemContainerTemplate="False">
                <MenuItem.Icon>
                    <Rectangle Width="20" Height="20">
                        <Rectangle.Fill>
                            <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                                <GradientStop Color="#FF5DFF00" Offset="0"/>
                                <GradientStop Color="#FFC500FF" Offset="1"/>
                                <GradientStop Color="#FF0A7D8F" Offset="0.5"/>
                            </LinearGradientBrush>
                        </Rectangle.Fill>
                    </Rectangle>
                </MenuItem.Icon>
            </MenuItem>
            <Separator/>
            <CollectionContainer Collection="{Binding Source={StaticResource CustomColorCollection}}" />
        </CompositeCollection>
    </MenuItem.ItemsSource>
    <MenuItem.ItemTemplate>
        <DataTemplate> <!-- this should only be used for the CustomColorCollection -->
            <MenuItem x:Name="MyMenuItem" Header="{Binding Title}">
                <MenuItem.Icon>
                    <Rectangle Width="20" Height="20" Fill="{Binding Color}"/>
                </MenuItem.Icon>
            </MenuItem>
        </DataTemplate>
    </MenuItem.ItemTemplate>
    <MenuItem.ItemContainerStyle>  <!-- this should only be used for the CustomColorCollection -->
        <Style TargetType="MenuItem">
            <Setter Property="Background" Value="{Binding Path=Background, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ContextMenu}}"/>
            <Setter Property="Command" Value="{Binding Path=DataContext.SetColorCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ContextMenu}}"/>
            <Setter Property="CommandParameter" Value="{Binding Color}"/>
        </Style>
    </MenuItem.ItemContainerStyle>
</MenuItem>

P.S.:This one 有所帮助,但与我的问题仍有一些不同,因为我无法在 DataTemplate 中为建议的 TextBlock 设置 Command 和 CommandParameter。

【问题讨论】:

    标签: c# wpf xaml menu contextmenu


    【解决方案1】:

    我现在有一个可行的解决方案!

    第一件事:我根本不需要使用 DataTemplate。 其次是在资源中添加一个矩形: &lt;Rectangle x:Key="ColorRectangle" x:Shared="False" Width="20" Height="20" Fill="{Binding Color}" /&gt;

    第三件事是更改 ItemContainerStyle 以使用定义的 &lt;Rectangle&gt; 并使用 MenuItems 的一般样式(通过 BasedOn):

    <MenuItem.ItemContainerStyle>
        <Style TargetType="MenuItem" BasedOn="{StaticResource {x:Type MenuItem}}">
            <Setter Property="Header" Value="{Binding Title}"/>
            <Setter Property="Icon" Value="{StaticResource ColorRectangle}" />
            <Setter Property="Command" Value="{Binding Path=DataContext.SetColorCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ContextMenu}}"/>
            <Setter Property="CommandParameter" Value="{Binding Color}"/>
        </Style>
    </MenuItem.ItemContainerStyle>
    

    为了完整起见,这是完整的代码:

    <MenuItem Header="Colors">
        <MenuItem.Resources>
            <CollectionViewSource x:Key="CustomColorCollection" Source="{Binding ColorList}"/>
            <Rectangle x:Key="ColorRectangle" x:Shared="False" Width="20" Height="20" Fill="{Binding Color}" />
        </MenuItem.Resources>
        <MenuItem.ItemsSource>
            <CompositeCollection>
                <MenuItem Header="Reset color" Command="{Binding SetColorCommand}" CommandParameter="#DCDCDC" UsesItemContainerTemplate="False">
                    <!--this is TextColorBrush-->
                    <MenuItem.Icon>
                        <Rectangle Width="20" Height="20" Fill="#DCDCDC"/>
                    </MenuItem.Icon>
                </MenuItem>
                <MenuItem Header="Custom color" Command="{Binding SetColorCommand}" CommandParameter="custom" UsesItemContainerTemplate="False">
                    <MenuItem.Icon>
                        <Rectangle Width="20" Height="20">
                            <Rectangle.Fill>
                                <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                                    <GradientStop Color="#FF5DFF00" Offset="0"/>
                                    <GradientStop Color="#FFC500FF" Offset="1"/>
                                    <GradientStop Color="#FF0A7D8F" Offset="0.5"/>
                                </LinearGradientBrush>
                            </Rectangle.Fill>
                        </Rectangle>
                    </MenuItem.Icon>
                </MenuItem>
                <Separator/>
                <CollectionContainer Collection="{Binding Source={StaticResource CustomColorCollection}}" />
            </CompositeCollection>
        </MenuItem.ItemsSource>
        <MenuItem.ItemContainerStyle>
            <Style TargetType="MenuItem" BasedOn="{StaticResource {x:Type MenuItem}}">
                <Setter Property="Header" Value="{Binding Title}"/>
                <Setter Property="Icon" Value="{StaticResource ColorRectangle}" />
                <Setter Property="Command" Value="{Binding Path=DataContext.SetColorCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ContextMenu}}"/>
                <Setter Property="CommandParameter" Value="{Binding Color}"/>
            </Style>
        </MenuItem.ItemContainerStyle>
    </MenuItem>
    

    只剩下一个问题:对于静态条目(即“重置颜色”和“自定义颜色”),我在 Visual Studio 2017 的输出窗口中收到以下警告:

    System.Windows.Data Error: 40 : BindingExpression path error: 'Title' property not found on 'object' ''SoundtrackRow' (HashCode=9307971)'. BindingExpression:Path=Title; DataItem='SoundtrackRow' (HashCode=9307971); target element is 'MenuItem' (Name=''); target property is 'Header' (type 'Object')
    System.Windows.Data Error: 40 : BindingExpression path error: 'Color' property not found on 'object' ''SoundtrackRow' (HashCode=9307971)'. BindingExpression:Path=Color; DataItem='SoundtrackRow' (HashCode=9307971); target element is 'MenuItem' (Name=''); target property is 'CommandParameter' (type 'Object')
    

    它们当然是,因为静态条目不能绑定到标题和颜色,因为它们根本不存在。

    如何消除这些警告?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多