[英]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.