简体   繁体   English

WPF:带有静态和动态条目和命令绑定的上下文菜单菜单项

[英]WPF: Contextmenu MenuItem with static and dynamic entries and Command binding

I have a Contextmenu which contains MenuItems.我有一个包含 MenuItems 的上下文菜单。 So far, so good.到现在为止还挺好。 In a submenu ("Colors"), I want to have static entries ("Reset color" and "Custom color") as well a dynamic values.在子菜单(“颜色”)中,我想要静态条目(“重置颜色”和“自定义颜色”)以及动态值。 It currently looks like this: Contextmenu .它目前看起来像这样: Contextmenu

So, my question is:所以,我的问题是:

What do I need to do to get the same styling for both: static and dynamic (via my CustomColorCollection) entries and still have the possibility to separately set the Command and CommandParameter?我需要做什么才能获得相同的样式:静态和动态(通过我的 CustomColorCollection)条目,并且仍然可以单独设置 Command 和 CommandParameter?

The dynamic values are bound to a public static ObservableCollection<ContextMenuColor> ColorList { get; set; } = new ObservableCollection<ContextMenuColor>()动态值绑定到public static ObservableCollection<ContextMenuColor> ColorList { get; set; } = new ObservableCollection<ContextMenuColor>() public static ObservableCollection<ContextMenuColor> ColorList { get; set; } = new ObservableCollection<ContextMenuColor>() public static ObservableCollection<ContextMenuColor> ColorList { get; set; } = new ObservableCollection<ContextMenuColor>() with ContextMenuColor being a small class like this: 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;
        }
    }

When I click on a menuitem, I want it to run my ICommand SetColorCommand with ContextMenuColor.Color as a CommandParameter.当我单击菜单项时,我希望它以 ContextMenuColor.Color 作为 CommandParameter 运行我的 ICommand SetColorCommand。

This is what I have so far in my XAML:这是我迄今为止在 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>

PS: This one helped but is still a little different from my problem as I was unable to set Command and CommandParameter for the proposed TextBlock in the DataTemplate. PS: 这个有帮助,但与我的问题仍有一点不同,因为我无法在 DataTemplate 中为建议的 TextBlock 设置 Command 和 CommandParameter。

I now have a working solution!我现在有一个有效的解决方案!

First thing: I do not have to use a DataTemplate at all.第一件事:我根本不必使用 DataTemplate。 Second was to add a rectangle in the Resources: <Rectangle x:Key="ColorRectangle" x:Shared="False" Width="20" Height="20" Fill="{Binding Color}" />其次是在资源中添加一个矩形: <Rectangle x:Key="ColorRectangle" x:Shared="False" Width="20" Height="20" Fill="{Binding Color}" />

Third thing was to change the ItemContainerStyle to use the defined <Rectangle> and also use the general style for MenuItems (via BasedOn ):第三件事是更改 ItemContainerStyle 以使用定义的<Rectangle>并使用 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>

For completeness, this is the full code:为了完整起见,这是完整的代码:

<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>

Only one question remains: for the static entries (ie "Reset color" and "Custom color") I get these warnings in the Output window of Visual Studio 2017:只剩下一个问题:对于静态条目(即“重置颜色”和“自定义颜色”),我在 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')

They are, of course, since the static entries can not bind to Title and Color as they simply do not exist for them.当然,它们是,因为静态条目不能绑定到 Title 和 Color,因为它们根本不存在。

How can I get rid of these warnings?我怎样才能摆脱这些警告?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM