【问题标题】:WPF XAML - Inherit Bursh from Parent to Fascilitate Icon ReuseWPF XAML - 从父级继承画笔以促进图标重用
【发布时间】:2016-11-25 17:00:50
【问题描述】:

我的 WPF 应用中有以下结构:

App.xaml:

<Application.Resources>
    <ResourceDictionary>
        <DrawingImage x:Key="mycion">
            <DrawingImage.Drawing>
                <GeometryDrawing Brush="{WHAT DO I PUT HERE?}" Geometry="M8,8L56,8 56,13.375 8,13.375 8,8z M8,24L8,18.625 56,18.625 56,24 8,24z M8,34.625L8,29.375 56,29.375 56,34.625 8,34.625z M8,45.375L8,40 56,40 56,45.375 8,45.375z M8,56L8,50.625 56,50.625 56,56 8,56z" />
            </DrawingImage.Drawing>
        </DrawingImage>
    </ResourceDictionary>
</Application.Resources>

Window1.xaml:

<Button HorizontalAlignment="Left" Height="49" Margin="33,36,0,0" VerticalAlignment="Top" Width="115">
    <!-- I want this image to be Red. -->
    <Image Height="25" Width="42" Source="{StaticResource mycion}"/>
</Button>

<Button HorizontalAlignment="Left" Height="49" Margin="33,136,0,0" VerticalAlignment="Top" Width="115">
    <!-- I want this image to be Green. -->
    <Image Height="25" Width="42" Source="{StaticResource mycion}"/>
</Button>

问题:

我如何允许更改绑定到期望ImageSource 的属性的资源(资源字典中的自定义图标实现为DrawingImage)的画笔颜色(在我的示例中为红色/绿色)?

基本上,我希望能够以某种方式将我的图标在 ResourceDictionaries 中定义为几何图形,但能够轻松地将这些图标设置为期望 ImageSource 的属性的值,并且能够更改/设置画笔用于在父对象或窗口的 XAML 中以某种方式呈现该几何图形(因此它会向下传播到图标资源)。

注意:我使用嵌套在Button 中的Image 仅作为示例。图标不一定要设置在图像上,但更常见的是作为其他元素的属性值,需要ImageSource

我也对其他可能性持开放态度 - 不仅仅是使用 DrawingImage,但我对 WPF 相对较新,所以不知道如何轻松实现它,因为:

  • 我的图标表示为几何图形
  • 我确实需要能够基于每个 UIElement(使用图标)设置画笔
  • 我不想将图标设置为元素的(一部分)内容 - 这太麻烦和复杂(处理简单按钮的布局 - 如果您想要同时拥有图标和文本等) .

任何关于此事的提示将不胜感激。

【问题讨论】:

    标签: wpf xaml imagesource


    【解决方案1】:

    将几何存储为资源,因为它是最难重复的部分 (DRY)

    <Geometry x:Key="ico">M8,8L56,8 56,13.375 8,13.375 8,8z M8,24L8,18.625 56,18.625 56,24 8,24z M8,34.625L8,29.375 56,29.375 56,34.625 8,34.625z M8,45.375L8,40 56,40 56,45.375 8,45.375z M8,56L8,50.625 56,50.625 56,56 8,56z</Geometry>
    

    并为每种颜色创建一个DrawingImage(GeometryDrawing与DrawingImage分开以使代码更短)

    <GeometryDrawing x:Key="red"  Brush="Red" Geometry="{StaticResource ico}" />
    <DrawingImage x:Key="redIcon" Drawing="{StaticResource red}"/>
    
    <GeometryDrawing x:Key="green"  Brush="Green" Geometry="{StaticResource ico}" />
    <DrawingImage x:Key="greenIcon" Drawing="{StaticResource green}"/>
    

    用法

    <Button HorizontalAlignment="Left" Height="49"  VerticalAlignment="Top" Width="115">
        <Image Height="25" Width="42" Source="{StaticResource redIcon}"/>
    </Button>
    
    <Button HorizontalAlignment="Left" Height="49" VerticalAlignment="Top" Width="115">
        <Image Height="25" Width="42" Source="{StaticResource greenIcon}"/>
    </Button>
    

    如果需要很多颜色,最好创建一个转换器,它将使用几何资源并返回所需颜色的 DrawingImage


    我正在谈论的转换器示例:
    public class GeometryColorConverter: IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            // getting geometry from App resources
            var g = (Geometry)value;
    
            // set Black as default color 
            string colorName = (string)parameter ?? "Black";
    
            // parsing color name
            var color = (Color)ColorConverter.ConvertFromString(colorName);
    
            // creating Image
            return new DrawingImage
            {
                Drawing = new GeometryDrawing(new SolidColorBrush(color), null, g)
            };            
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
    

    及用法:

    <local:GeometryColorConverter x:Key="paint"/>
    
    <Button HorizontalAlignment="Left" Height="49" VerticalAlignment="Top" Width="115">
        <Image Height="25" Width="42" 
            Source="{Binding Source={StaticResource ico}, 
                             Converter={StaticResource paint}, 
                             ConverterParameter=Orange}"/>
    </Button>
    

    【讨论】:

    • 感谢您的提示!是的,我当然更喜欢只存储几何图形并依赖转换器或转换器。您能否修改您的答案以提供转换器的示例用法?理想情况下,在伪代码中我想要这样的东西(据我了解,它应该可以使用转换器):&lt;Button Image="{SomeConverter {StaticResource myicongeometry} mydesiredbrush}" /&gt; 但我不确定我如何实际实现它,成本是多少(以这种方法的 CPU 和内存 - 我计划有 100 个这样的元素)。
    • @FitDev,我添加了一个示例。 100 个元素将需要 100 个图像。基于资源的方法更便宜,但这样您就可以轻松使用任何颜色而无需制作新资源
    • 感谢您的帮助!这几乎就是我想要的。不过,我问的是使用这种 ValueConverters 处理 100 个图标/元素的成本,就 CPU/内存而言?
    • 哦,还有一件事……在您实现IValueConverter 的示例中,该图标是硬编码的,但它必须是“从”XAML 读取的参数。关键是转换器应该与图标无关。基本上它接受一个图标(几何)和一个画笔并输出 DrawingImage
    • @FitDev,它在 cpu/内存方面非常快速和便宜。我对 App.Resources["ico"] 的错误,当然应该是 value,已修复
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-02
    相关资源
    最近更新 更多