我确信其他人找到了办法,我很接近但不完全。 我使用StaticResourceConverter类成功地使用基于资源名称绑定到资源的Geometry的Path对象:
public class StaticResourceConverter: BaseConverter, IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if(System.Convert.ToString(value).IsNullOrEmpty())
{
return null;
}
var resource = Application.Current.Resources[value];
return resource;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new Exception("The method or operation is not implemented.");
}
}
绑定到MenuItem中的Image对象需要使用相同的方法创建一个带有底层DrawingImage的Image实例:
<Style TargetType="{x:Type MenuItem}">
<Setter Property="Icon">
<Setter.Value>
<Image Style="{StaticResource ResourceKey=SpMenuItemIcon}">
<Image.Source>
<DrawingImage>
<DrawingImage.Drawing>
<GeometryDrawing
Brush="{StaticResource SpIconPath}"
Geometry="{Binding IconPath,
Converter={converters:StaticResourceConverter}}"/>
</DrawingImage.Drawing>
</DrawingImage>
</Image.Source>
</Image>
</Setter.Value>
</Setter>
</Style>
问题是我怀疑只创建了一个Image实例,或者只绑定了1个实例,因为只有菜单中的最后一个图标才能显示正确的几何路径。为什么WPF只绑定最后一个MenuItem以及如何使它适用于所有菜单项?
更新
这里只是为了帮助测试,几个示例几何资源要绑定到(使用Key):
<Geometry x:Key="ExpandIconPath">F1 M 30.25,58L 18,58L 18,45.75L 22,41.75L 22,50.75L 30,42.75L 33.25,46L 25.25,54L 34.25,54L 30.25,58 Z M 58,45.75L 58,58L 45.75,58L 41.75,54L 50.75,54L 42.75,46L 46,42.75L 54,50.75L 54,41.75L 58,45.75 Z M 45.75,18L 58,18L 58,30.25L 54,34.25L 54,25.25L 46,33.25L 42.75,30L 50.75,22L 41.75,22L 45.75,18 Z M 18,30.25L 18,18L 30.25,18L 34.25,22L 25.25,22L 33.25,30L 30,33.25L 22,25.25L 22,34.25L 18,30.25 Z</Geometry>
<Geometry x:Key="CollapseIconPath">F1 M 54.2499,34L 42,34L 42,21.7501L 45.9999,17.7501L 45.9999,26.7501L 53.9999,18.7501L 57.2499,22.0001L 49.2499,30.0001L 58.2499,30.0001L 54.2499,34 Z M 34,21.7501L 34,34L 21.75,34L 17.75,30.0001L 26.75,30.0001L 18.75,22.0001L 22,18.7501L 30,26.7501L 30,17.7501L 34,21.7501 Z M 21.75,42L 34,42L 34,54.25L 30,58.25L 30,49.25L 22,57.25L 18.75,54L 26.75,46L 17.75,46L 21.75,42 Z M 42,54.25L 42,42L 54.2499,42L 58.2499,46L 49.2499,46.0001L 57.2499,54L 53.9999,57.25L 45.9999,49.25L 45.9999,58.25L 42,54.25 Z</Geometry>
<Geometry x:Key="CloseIconPath">F1 M 26.9166,22.1667L 37.9999,33.25L 49.0832,22.1668L 53.8332,26.9168L 42.7499,38L 53.8332,49.0834L 49.0833,53.8334L 37.9999,42.75L 26.9166,53.8334L 22.1666,49.0833L 33.25,38L 22.1667,26.9167L 26.9166,22.1667 Z</Geometry>
答案 0 :(得分:5)
将x:Shared
属性设置为false
,以防止在应用样式的所有位置重复使用样式资源,从而避免使用Image
:
<Style TargetType="{x:Type MenuItem}" x:Shared="False">
<Setter Property="Icon">
...
</Setter>
</Style>
答案 1 :(得分:5)
与Clemens建议的不同,您不需要使整个Style
不共享。问题来自Image
,MenuItem
必须是唯一的Image
。因此,只有将x:Shared
设置为False
时才将<Window x:Class="So19902960WpfMenuItemIconGeometry.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:So19902960WpfMenuItemIconGeometry"
Title="MainWindow" Height="350" Width="525">
<Control.Resources>
<local:StaticResourceConverter x:Key="StaticResourceConverter"/>
<Geometry x:Key="ExpandIconPath">F1 M 30.25,58L 18,58L 18,45.75L 22,41.75L 22,50.75L 30,42.75L 33.25,46L 25.25,54L 34.25,54L 30.25,58 Z M 58,45.75L 58,58L 45.75,58L 41.75,54L 50.75,54L 42.75,46L 46,42.75L 54,50.75L 54,41.75L 58,45.75 Z M 45.75,18L 58,18L 58,30.25L 54,34.25L 54,25.25L 46,33.25L 42.75,30L 50.75,22L 41.75,22L 45.75,18 Z M 18,30.25L 18,18L 30.25,18L 34.25,22L 25.25,22L 33.25,30L 30,33.25L 22,25.25L 22,34.25L 18,30.25 Z</Geometry>
<Geometry x:Key="CollapseIconPath">F1 M 54.2499,34L 42,34L 42,21.7501L 45.9999,17.7501L 45.9999,26.7501L 53.9999,18.7501L 57.2499,22.0001L 49.2499,30.0001L 58.2499,30.0001L 54.2499,34 Z M 34,21.7501L 34,34L 21.75,34L 17.75,30.0001L 26.75,30.0001L 18.75,22.0001L 22,18.7501L 30,26.7501L 30,17.7501L 34,21.7501 Z M 21.75,42L 34,42L 34,54.25L 30,58.25L 30,49.25L 22,57.25L 18.75,54L 26.75,46L 17.75,46L 21.75,42 Z M 42,54.25L 42,42L 54.2499,42L 58.2499,46L 49.2499,46.0001L 57.2499,54L 53.9999,57.25L 45.9999,49.25L 45.9999,58.25L 42,54.25 Z</Geometry>
<Geometry x:Key="CloseIconPath">F1 M 26.9166,22.1667L 37.9999,33.25L 49.0832,22.1668L 53.8332,26.9168L 42.7499,38L 53.8332,49.0834L 49.0833,53.8334L 37.9999,42.75L 26.9166,53.8334L 22.1666,49.0833L 33.25,38L 22.1667,26.9167L 26.9166,22.1667 Z</Geometry>
<Image x:Key="MenuItemImage" x:Shared="False" Width="16" Height="16">
<Image.Source>
<DrawingImage>
<DrawingImage.Drawing>
<GeometryDrawing Brush="Blue"
Geometry="{Binding Tag,
RelativeSource={RelativeSource AncestorType=MenuItem},
Converter={StaticResource StaticResourceConverter}}"/>
</DrawingImage.Drawing>
</DrawingImage>
</Image.Source>
</Image>
<Style TargetType="MenuItem">
<Setter Property="Icon" Value="{StaticResource MenuItemImage}"/>
</Style>
</Control.Resources>
<Menu>
<MenuItem Header="Expand" Tag="ExpandIconPath"/>
<MenuItem Header="Collapse" Tag="CollapseIconPath"/>
<MenuItem Header="Close" Tag="CloseIconPath"/>
</Menu>
</Window>
放入资源中,才能使using System;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
namespace So19902960WpfMenuItemIconGeometry
{
public partial class MainWindow
{
public MainWindow ()
{
InitializeComponent();
}
}
public class StaticResourceConverter : IValueConverter
{
public object Convert (object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == DependencyProperty.UnsetValue || value == null)
return DependencyProperty.UnsetValue;
return Application.Current.MainWindow.Resources[value];
}
public object ConvertBack (object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotSupportedException();
}
}
}
无法共享。
一个工作自包含的例子:
<强> MainWindow.xaml 强>
NotSupportedException
<强> MainWindow.xaml.cs 强>
Exception
注意:
您应该在ConvertBack
方法中使用自定义消息抛出DependencyProperty.UnsetValue
而不是Convert
。它特别适用于未实施和不实施某种方法的情况。
您应该在{{1}}方法中检查{{1}}。当绑定失败时,转换器不应该使应用程序崩溃。