我试图将一些定义 MenuItem 的XAML移动到样式。
我有以下工作XAML:
<Menu x:Name="menu" Height="19" Margin="10,10,10.333,0" VerticalAlignment="Top">
<MenuItem Header="_Open">
<MenuItem.Icon>
<Viewbox>
<ContentControl Content="{DynamicResource appbar.folder.open}" RenderTransformOrigin="0.5,0.5">
<ContentControl.RenderTransform>
<TransformGroup>
<ScaleTransform ScaleX="2" ScaleY="2"/>
</TransformGroup>
</ContentControl.RenderTransform>
</ContentControl>
</Viewbox>
</MenuItem.Icon>
</MenuItem>
</Menu>
资源如下所示:
<?xml version="1.0" encoding="utf-8"?>
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Canvas xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Key="appbar.folder.open" Width="76" Height="76" Clip="F1 M 0,0L 76,0L 76,76L 0,76L 0,0">
<Path Width="44" Height="26" Canvas.Left="19" Canvas.Top="24" Stretch="Fill" Fill="#FF000000" Data="F1 M 19,50L 28,34L 63,34L 54,50L 19,50 Z M 19,28.0001L 35,28C 36,25 37.4999,24.0001 37.4999,24.0001L 48.75,24C 49.3023,24 50,24.6977 50,25.25L 50,28L 53.9999,28.0001L 53.9999,32L 27,32L 19,46.4L 19,28.0001 Z "/>
</Canvas>
</ResourceDictionary>
作为旁注,我也不知道如何摆脱明确的缩放。这似乎是一个小问题,但如果这也可以解决,我将不胜感激。
无论如何,为了尽可能地将这个有点过于表达的定义移动到Style中,我为Visual类型的附加属性创建了代码
namespace extensions
{
public class AttachedProperties
{
public static readonly DependencyProperty VisualIconProperty =
DependencyProperty.RegisterAttached("VisualIcon",
typeof(System.Windows.Media.Visual), typeof(AttachedProperties),
new PropertyMetadata(default(System.Windows.Media.Visual)));
public static void SetVisualIcon(UIElement element, System.Windows.Media.Visual value)
{
element.SetValue(VisualIconProperty, value);
}
public static System.Windows.Media.Visual GetVisualIcon(UIElement element)
{
return (System.Windows.Media.Visual)element.GetValue(VisualIconProperty);
}
}
}
重新定义了菜单项
<MenuItem Header="_Open"
Style="{StaticResource MenuItemStyle}"
extensions:AttachedProperties.VisualIcon="{DynamicResource appbar.folder.open}" />
并尝试创建一个Style,它读取VisualIcon属性以设置Icon内容
<Style x:Key="MenuItemStyle" TargetType="MenuItem">
<Setter Property="MenuItem.Icon">
<Setter.Value>
<Viewbox>
<ContentControl RenderTransformOrigin="0.5,0.5">
<ContentControl.Content>
<!-- this would work but doesn't reference the VisualIcon property.. <DynamicResource ResourceKey="appbar.folder.open"/> -->
<!-- these do not -->
<Binding Path="(extensions:AttachedProperties.VisualIcon)" RelativeSource="{RelativeSource FindAncestor, AncestorType=MenuItem}"/>-->
<!--<Binding Path="(extensions:AttachedProperties.VisualIcon)" RelativeSource="{RelativeSource TemplatedParent}"/>-->
<!--<Binding Path="(extensions:AttachedProperties.VisualIcon)" RelativeSource="{RelativeSource Self}"/>-->
</ContentControl.Content>
<ContentControl.RenderTransform>
<TransformGroup>
<ScaleTransform ScaleX="2" ScaleY="2"/>
</TransformGroup>
</ContentControl.RenderTransform>
</ContentControl>
</Viewbox>
</Setter.Value>
</Setter>
</Style>
但失败了。使用DynamicResource和静态密钥引用资源有效,但我无法使用附加属性进行任何绑定。
由于我是WPF初学者,我不确定这是否是一个好方法。
[EDIT1]
我测试了所有提供的解决方案。 Grek40 answer在设计视图和运行时都没有为我显示任何图标;也许我做错了。
grx70 second answer中的第二种方法对我来说最有希望,因为它可以在设计视图中以及在运行时间内可靠地显示图标。 但是,似乎Win7和Win10之间存在差异我不明白。我在Win7和Win10上测试了相同的源(在外部驱动器上)。对于Win10来说,它看起来不错,但是Win7的图标太大了。
(注意:原因在于this comment)
这是窗口测试代码:
<Window.Resources>
<Style x:Key="MenuItemStyle" TargetType="controls:MenuItemEx">
<Setter Property="MenuItem.Icon">
<Setter.Value>
<Viewbox>
<ContentControl RenderTransformOrigin="0.5,0.5">
<ContentControl.Content>
<Binding Path="(extensions:AttachedProperties.VisualIcon)" RelativeSource="{RelativeSource FindAncestor, AncestorType=MenuItem}"/>
</ContentControl.Content>
<ContentControl.RenderTransform>
<TransformGroup>
<ScaleTransform ScaleX="2" ScaleY="2"/>
</TransformGroup>
</ContentControl.RenderTransform>
</ContentControl>
</Viewbox>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="MenuItemStyle2" TargetType="MenuItem">
<Setter Property="uihelpers:MenuItemHelper.IsEnabled" Value="True" />
<Setter Property="MenuItem.Icon">
<Setter.Value>
<Viewbox>
<ContentControl RenderTransformOrigin="0.5,0.5"
Content="{Binding
Path=(uihelpers:MenuItemHelper.MenuItem).(extensions:AttachedProperties.VisualIcon),
RelativeSource={RelativeSource AncestorType=Viewbox}}">
<ContentControl.RenderTransform>
<TransformGroup>
<ScaleTransform ScaleX="2" ScaleY="2"/>
</TransformGroup>
</ContentControl.RenderTransform>
</ContentControl>
</Viewbox>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="MenuItemStyle3" TargetType="{x:Type MenuItem}">
<Style.Resources>
<DataTemplate x:Key="MenuItemStyle3dt" DataType="{x:Type Style}">
<Path Style="{Binding}"
Stretch="Uniform"
HorizontalAlignment="Center"
VerticalAlignment="Center" />
</DataTemplate>
</Style.Resources>
</Style>
<Style x:Key="appbar.folder.open.style3.local" TargetType="{x:Type Path}">
<Setter Property="Fill" Value="Black" />
<Setter Property="Data" Value="M0,26 L9,10 L44,10 L35,26 Z M0,4 L16,4 C17,1 18.5,0 18.5,0 L29.75,0 C30.3,0 31,0.7 31,1.25 L31,4 L34,4 L34,8 L8,8 L0,22.4 Z" />
</Style>
<extensions:PathStyle x:Key="appbar.folder.open.style3b">
<Setter Property="Path.HorizontalAlignment" Value="Center" />
<Setter Property="Path.VerticalAlignment" Value="Center" />
<Setter Property="Path.Stretch" Value="Uniform" />
<Setter Property="Path.Fill" Value="Black" />
<Setter Property="Path.Data" Value="M0,26 L9,10 L44,10 L35,26 Z M0,4 L16,4 C17,1 18.5,0 18.5,0 L29.75,0 C30.3,0 31,0.7 31,1.25 L31,4 L34,4 L34,8 L8,8 L0,22.4 Z" />
</extensions:PathStyle>
<DataTemplate DataType="{x:Type extensions:PathStyle}">
<Path Style="{Binding}" />
</DataTemplate>
<Canvas x:Key="appbar.folder.open.style4.local" x:Shared="False" Width="76" Height="76" Clip="F1 M 0,0L 76,0L 76,76L 0,76L 0,0">
<Path Width="44" Height="26" Canvas.Left="19" Canvas.Top="24" Stretch="Fill" Fill="#FF000000" Data="F1 M 19,50L 28,34L 63,34L 54,50L 19,50 Z M 19,28.0001L 35,28C 36,25 37.4999,24.0001 37.4999,24.0001L 48.75,24C 49.3023,24 50,24.6977 50,25.25L 50,28L 53.9999,28.0001L 53.9999,32L 27,32L 19,46.4L 19,28.0001 Z "/>
</Canvas>
<Viewbox x:Key="MenuItemStyle4.Icon" x:Shared="False">
<ContentControl Content="{Binding Path=Tag,RelativeSource={RelativeSource AncestorType=MenuItem}}" RenderTransformOrigin="0.5,0.5">
<ContentControl.RenderTransform>
<TransformGroup>
<ScaleTransform ScaleX="2" ScaleY="2"/>
</TransformGroup>
</ContentControl.RenderTransform>
</ContentControl>
</Viewbox>
<Style x:Key="MenuItemStyle4" TargetType="MenuItem">
<Setter Property="Icon" Value="{StaticResource MenuItemStyle4.Icon}"/>
</Style>
</Window.Resources>
<Grid>
<Menu x:Name="menu" Height="19" Margin="10,10,10.333,0" VerticalAlignment="Top">
<MenuItem Header="_File">
<controls:MenuItemEx Header="_Open"
Style="{StaticResource MenuItemStyle}"
extensions:AttachedProperties.VisualIcon="{DynamicResource appbar.folder.open}" />
<MenuItem Header="_Open"
Style="{StaticResource MenuItemStyle2}"
extensions:AttachedProperties.VisualIcon="{DynamicResource appbar.folder.open}" />
<MenuItem Header="_Open"
Style="{StaticResource MenuItemStyle3}"
Icon="{DynamicResource appbar.folder.open.style3}" />
<MenuItem Header="_Open"
Style="{StaticResource MenuItemStyle3}"
Icon="{DynamicResource appbar.folder.open.style3.local}" />
<MenuItem Header="_Open" Icon="{DynamicResource appbar.folder.open.style3b}" />
<MenuItem Header="_Open"
Style="{StaticResource MenuItemStyle4}"
Tag="{DynamicResource appbar.folder.open}" />
<MenuItem Header="_Open"
Style="{StaticResource MenuItemStyle4}"
Tag="{DynamicResource appbar.folder.open.style4.local}" />
<MenuItem Header="_Save">
<MenuItem.Icon>
<Viewbox>
<ContentControl Content="{DynamicResource appbar.save}" RenderTransformOrigin="0.5,0.5">
<ContentControl.RenderTransform>
<TransformGroup>
<ScaleTransform ScaleX="2" ScaleY="2"/>
</TransformGroup>
</ContentControl.RenderTransform>
</ContentControl>
</Viewbox>
</MenuItem.Icon>
</MenuItem>
</MenuItem>
</Menu>
<Menu x:Name="menu2" Height="19" Margin="9,32,11.333,0" VerticalAlignment="Top" ItemContainerStyle="{StaticResource MenuItemStyle4}">
<MenuItem Header="_File">
<MenuItem Header="_Open"
Tag="{DynamicResource appbar.folder.open.style4.local}" />
<MenuItem Header="_Open"
Tag="{DynamicResource appbar.folder.open}" />
</MenuItem>
</Menu>
</Grid>
以下是全球资源:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Canvas xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Key="appbar.folder.open" x:Shared="False" Width="76" Height="76" Clip="F1 M 0,0L 76,0L 76,76L 0,76L 0,0">
<Path Width="44" Height="26" Canvas.Left="19" Canvas.Top="24" Stretch="Fill" Fill="#FF000000" Data="F1 M 19,50L 28,34L 63,34L 54,50L 19,50 Z M 19,28.0001L 35,28C 36,25 37.4999,24.0001 37.4999,24.0001L 48.75,24C 49.3023,24 50,24.6977 50,25.25L 50,28L 53.9999,28.0001L 53.9999,32L 27,32L 19,46.4L 19,28.0001 Z "/>
</Canvas>
<Style x:Key="appbar.folder.open.style3" TargetType="{x:Type Path}">
<Setter Property="Fill" Value="Black" />
<Setter Property="Data" Value="M0,26 L9,10 L44,10 L35,26 Z M0,4 L16,4 C17,1 18.5,0 18.5,0 L29.75,0 C30.3,0 31,0.7 31,1.25 L31,4 L34,4 L34,8 L8,8 L0,22.4 Z" />
</Style>
</ResourceDictionary>
和
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Canvas xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Key="appbar.save" Width="76" Height="76" Clip="F1 M 0,0L 76,0L 76,76L 0,76L 0,0">
<Path Width="34.8333" Height="34.8333" Canvas.Left="20.5833" Canvas.Top="20.5833" Stretch="Fill" Fill="#FF000000" Data="F1 M 20.5833,20.5833L 55.4167,20.5833L 55.4167,55.4167L 45.9167,55.4167L 45.9167,44.3333L 30.0833,44.3333L 30.0833,55.4167L 20.5833,55.4167L 20.5833,20.5833 Z M 33.25,55.4167L 33.25,50.6667L 39.5833,50.6667L 39.5833,55.4167L 33.25,55.4167 Z M 26.9167,23.75L 26.9167,33.25L 49.0833,33.25L 49.0833,23.75L 26.9167,23.75 Z "/>
</Canvas>
</ResourceDictionary>
在app.xaml中合并:
<Application.Resources>
<ResourceDictionary >
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="icons/appbar.folder.open.xaml"/>
<ResourceDictionary Source="icons/appbar.save.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
图标被偏移的原因是我从github.com/Templarian/WindowsIcons或多或少1:1获取它们并且希望因为它们以这种格式提供(我也试图将它们保存为画笔,首先使用Inkscape,然后使用Expression Design),通常会像这样使用它们。
答案 0 :(得分:1)
绑定不起作用的原因如下:
RelativeSourceMode.Self
- 因为未在VisualIcon
上明确设置ContentControl
附加属性,其默认值为null
。RelativeSourceMode.TemplatedParent
- 因为ContentControl
不是模板的一部分(如果是,从您提供的代码中看不出来,可能是VisualIcon
的值对于模板化的父级是null
)RelativeSourceMode.FindAncestor
- 因为MenuItem
没有将MenuItem.Icon
属性的值设置为其逻辑子项,所以在将ContentControl
加载到可视树中之前,无法建立两者之间的关系。并且,显然,在这种情况下,绑定在此之前得到解决,并且由于某种原因在最终加载ContentControl
时没有重新解析。您可以采取几种方法来解决此问题,以下是其中一些方法。
<强>予。仅在加载ContentControl
您可以将以下处理程序订阅到ContentControl.Loaded
事件:
private void ContentControl_Loaded(object sender, RoutedEventArgs e)
{
var control = (ContentControl)sender;
control.SetBinding(ContentControl.ContentProperty, new Binding
{
Path = new PropertyPath(AttachedProperties.VisualIconProperty),
RelativeSource = new RelativeSource(RelativeSourceMode.FindAncestor)
{
AncestorType = typeof(MenuItem),
},
});
}
然后在 XAML :
中<ContentControl
Content="{Binding
Path=(extensions:AttachedProperties.VisualIcon),
RelativeSource={RelativeSource AncestorType=MenuItem}}"
Loaded="ContentControl_Loaded" (...)>
(...)
</ContentControl>
请注意,如果将样式放在单独文件的资源字典中,则必须按照these instructions进行操作。
您还可以创建自定义MarkupExtension
(例如,名为DeferredBinding
)来完成这项工作。
<强> II。子类MenuItem
并将图标设置为逻辑子
写的代码不多:
public class MyMenuItem : MenuItem
{
protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
{
base.OnPropertyChanged(e);
if (e.Property == IconProperty)
{
if (e.OldValue != null)
RemoveLogicalChild(e.OldValue);
if (e.NewValue != null)
AddLogicalChild(e.NewValue);
}
}
}
但缺点是你总是要记住使用MyMenuItem
代替MenuItem
:
<local:MyMenuItem Header="_Open"
Style="{StaticResource MenuItemStyle}"
extensions:AttachedProperties.VisualIcon="{DynamicResource appbar.folder.open}" />
和
<Style x:Key="MenuItemStyle" TargetType="local:MyMenuItem">
(...)
</Style>
在这种情况下,您还可以FindAncestor
模式进行绑定。
<强> III。创建一个帮助程序类,允许通过附加属性访问MenuItem
中的相关ContentControl
以下帮助器类包含两个依赖项属性 - IsEnabled
(我相信它是自我解释的)和MenuItem
,它是只读的并保存实际的MenuItem
,其中目标图标已设置:
public static class MenuItemHelper
{
/**** Here are the important parts: ****/
//When IsEnabled changes we need to either hook things up or do the cleanup
private static void HandleIsEnabledChanged(
DependencyObject d,
DependencyPropertyChangedEventArgs e)
{
var item = (MenuItem)d;
if ((bool)e.NewValue)
//We set MenuItem attached property for current Icon
HandleIconChanged(null, item, EventArgs.Empty);
else
//We clear the value of MenuItem attached property
HandleIconChanged(item.Icon, item, EventArgs.Empty);
}
//By using an extension method we get hold of the old value without the need
//to maintain any kind of dictionary, so we don't need to worry about memory leaks
private static void HandleIconChanged(
this object oldValue,
object sender,
EventArgs e)
{
var item = (MenuItem)sender;
if (oldValue is DependencyObject oldIcon)
SetMenuItem(oldIcon, null);
if (item.Icon is DependencyObject newIcon)
SetMenuItem(newIcon, item);
//We need to remove the old handler, because it relates to the old icon
DependencyPropertyDescriptor
.FromProperty(MenuItem.IconProperty, item.GetType())
.RemoveValueChanged(item, item.Icon.HandleIconChanged);
//We add new handler, so that when the icon changes we get correct old icon
DependencyPropertyDescriptor
.FromProperty(MenuItem.IconProperty, item.GetType())
.AddValueChanged(item, item.Icon.HandleIconChanged);
}
/**** The rest is just DP boilerplate code ****/
private static readonly DependencyPropertyKey MenuItemPropertyKey =
DependencyProperty.RegisterAttachedReadOnly(
name: "MenuItem",
propertyType: typeof(MenuItem),
ownerType: typeof(MenuItemHelper),
defaultMetadata: new PropertyMetadata(null));
public static readonly DependencyProperty MenuItemProperty =
MenuItemPropertyKey.DependencyProperty;
public static MenuItem GetMenuItem(DependencyObject d)
=> (MenuItem)d.GetValue(MenuItemProperty);
private static void SetMenuItem(DependencyObject d, MenuItem value)
=> d.SetValue(MenuItemPropertyKey, value);
public static readonly DependencyProperty IsEnabledProperty =
DependencyProperty.RegisterAttached(
name: "IsEnabled",
propertyType: typeof(bool),
ownerType: typeof(MenuItemHelper),
defaultMetadata: new PropertyMetadata(false, HandleIsEnabledChanged));
public static bool GetIsEnabled(MenuItem item)
=> (bool)item.GetValue(IsEnabledProperty);
public static void SetIsEnabled(MenuItem item, bool value)
=> item.SetValue(IsEnabledProperty, value);
}
然后您只需要在MenuItemHelper.IsEnabled="True"
上设置MenuItem
,然后您可以使用MenuItemHelper.MenuItem
进行绑定(请记住它将在图标的根元素上设置 - {{ 1}}在你的情况下):
Viewbox
我个人最喜欢的是#III,因为它是三者中最多才多艺的,但也许在你的特殊情况下,其他解决方案可能更适用。
答案 1 :(得分:1)
因为它有点像XY problem,所以我会给你另一种方法来实现你的目标。
首先,您的appbar.folder.open
资源过于复杂。 Canvas
完全是多余的(您可以通过设置Path
来抵消Margin
)。这些数字在Path
19,24
之内偏移,与Path
中的Canvas
相结合,导致必须将Viewbox
与{{}一起使用1}}。此外,您的资源不可重用,因为它只能加载到可视树中一次,因此它只能在引用的最后一个位置可见(它将在以前的所有位置卸载)。我的建议是为ScaleTransform
创建一个Style
- 不仅可以重复使用,还可以扩展,因为您可以在应用后修改目标Path
上的其他属性。样式。这是一个最小的风格来完成这项工作(我已经翻译了你的数据,以便它不再被抵消):
Path
其次,我不太明白你的<Style x:Key="appbar.folder.open" TargetType="{x:Type Path}">
<Setter Property="Fill" Value="Black" />
<Setter Property="Data" Value="M0,26 L9,10 L44,10 L35,26 Z M0,4 L16,4 C17,1 18.5,0 18.5,0 L29.75,0 C30.3,0 31,0.7 31,1.25 L31,4 L34,4 L34,8 L8,8 L0,22.4 Z" />
</Style>
附属财产的目的。在我的方法中,它是完全多余的。此外,我认为这是使设计人员在禁用项目代码时无法正确显示图标的部分。唯一的问题是,如果我们设置AttachedProperties.VisualIcon
,我们会显示MenuItem.Icon="{DynamicResource appbar.folder.open}"
文字而不是图标。 System.Windows.Style
不支持将引用的资源转换为开箱即用的资源。但是,我们可以使用一个聪明的技巧来使事情有效 - 只需提供一个隐含的DynamicResourceExtension
和DataTemplate
,它将自动应用:
DataType="{x:Type Style}"
我们在<Style x:Key="MenuItemStyle" TargetType="{x:Type MenuItem}">
<Style.Resources>
<DataTemplate DataType="{x:Type Style}">
<Path Style="{Binding}"
Stretch="Uniform"
HorizontalAlignment="Center"
VerticalAlignment="Center" />
</DataTemplate>
</Style.Resources>
</Style>
上设置了一些其他属性,以便它非常适合图标区域。
现在我们需要做的就是引用样式和图标,让它显示在Path
上:
MenuItem
这种方法的另一个优点是,即使禁用项目代码,它也可以在设计人员中工作(至少对我来说是这样)。
如果要完全分离和自动化事物,可以继承<Menu (...)>
<MenuItem Header="_Open"
Style="{StaticResource MenuItemStyle}"
Icon="{DynamicResource appbar.folder.open}" />
</Menu>
:
Style
并在资源字典中提供隐式public class PathStyle : Style
{
public PathStyle()
{
TargetType = typeof(Path);
}
}
:
DataTemplate
我将所有属性从<local:PathStyle x:Key="appbar.folder.open">
<Setter Property="Path.HorizontalAlignment" Value="Center" />
<Setter Property="Path.VerticalAlignment" Value="Center" />
<Setter Property="Path.Stretch" Value="Uniform" />
<Setter Property="Path.Fill" Value="Black" />
<Setter Property="Path.Data" Value="M0,26 L9,10 L44,10 L35,26 Z M0,4 L16,4 C17,1 18.5,0 18.5,0 L29.75,0 C30.3,0 31,0.7 31,1.25 L31,4 L34,4 L34,8 L8,8 L0,22.4 Z" />
</local:PathStyle>
<DataTemplate DataType="{x:Type local:PathStyle}">
<Path Style="{Binding}" />
</DataTemplate>
移动到DataTemplate
,以便可以在其他样式中覆盖它。请注意,您需要完全限定属性名称,即使用Style
而不是简单Path.Data
。
现在您只需要在视图中引用资源:
Data
甚至:
<MenuItem Icon="{DynamicResource appbar.folder.open}" (...) />
所有的魔力都是由框架完成的。这种方法的优点在于您可以将<ContentPresenter Content="{DynamicResource appbar.folder.open}" />
替换为包含例如:
ResourceDictionary
<Border x:Key="appbar.folder.open" x:Shared="False" Background="Red" />
一切仍然有效,无需修改视图。
答案 2 :(得分:0)
您的样式方法存在的问题是,在应用相同样式时,Viewbox
将在多个项目之间共享。通过将Viewbox
创建为具有x:Shared="False"
的单独资源,可以避免这种情况。如果您想坚持当前的Canvas-Path
方法,您应该将其转换为非共享资源,以便它可以重复使用
出于演示目的,我设置了MenuItem.Tag
属性,但是附加属性的想法应该是一样的。
资源:
<!--Notice the added x:Shared-->
<Canvas x:Key="appbar.folder.open" x:Shared="False" Width="76" Height="76" Clip="F1 M 0,0L 76,0L 76,76L 0,76L 0,0">
<Path Width="44" Height="26" Canvas.Left="19" Canvas.Top="24" Stretch="Fill" Fill="#FF000000" Data="F1 M 19,50L 28,34L 63,34L 54,50L 19,50 Z M 19,28.0001L 35,28C 36,25 37.4999,24.0001 37.4999,24.0001L 48.75,24C 49.3023,24 50,24.6977 50,25.25L 50,28L 53.9999,28.0001L 53.9999,32L 27,32L 19,46.4L 19,28.0001 Z "/>
</Canvas>
<!--Another icon for purpose of demonstration-->
<Canvas x:Key="appbar.folder.close" x:Shared="False" Width="76" Height="76" Clip="F1 M 0,0L 76,0L 76,76L 0,76L 0,0">
<Path Width="44" Height="26" Canvas.Left="19" Canvas.Top="24" Stretch="Fill" Fill="#FFFF0000" Data="F1 M 19,50L 28,34L 63,34L 54,50L 19,50 Z M 19,28.0001L 35,28C 36,25 37.4999,24.0001 37.4999,24.0001L 48.75,24C 49.3023,24 50,24.6977 50,25.25L 50,28L 53.9999,28.0001L 53.9999,32L 27,32L 19,46.4L 19,28.0001 Z "/>
</Canvas>
<Viewbox x:Key="MenuItemStyle.Icon" x:Shared="False">
<ContentControl Content="{Binding Path=Tag,RelativeSource={RelativeSource AncestorType=MenuItem}}" RenderTransformOrigin="0.5,0.5">
<ContentControl.RenderTransform>
<TransformGroup>
<ScaleTransform ScaleX="2" ScaleY="2"/>
</TransformGroup>
</ContentControl.RenderTransform>
</ContentControl>
</Viewbox>
<Style x:Key="MenuItemStyle" TargetType="MenuItem">
<Setter Property="Icon" Value="{StaticResource MenuItemStyle.Icon}"/>
</Style>
用法:
<Menu x:Name="menu" Height="19" Margin="10,10,10.333,0" VerticalAlignment="Top" ItemContainerStyle="{StaticResource MenuItemStyle}">
<MenuItem Header="_Open" Tag="{DynamicResource appbar.folder.open}"/>
<MenuItem Header="_Open 2" Tag="{DynamicResource appbar.folder.open}"/>
<MenuItem Header="_Close" Tag="{DynamicResource appbar.folder.close}"/>
</Menu>