如何参数化WPF按钮';s内容';子元素属性?

如何参数化WPF按钮';s内容';子元素属性?,wpf,Wpf,我的应用程序(使用MahApps.Metro)有许多元素和Content,除了本身的不同属性外,它们都有相同的标记,还有一个按钮。Content子元素属性我想通过一个新属性参数化(附加属性?) 我有大约20个按钮的XAML实例: <Button Style="{StaticResource MetroCircleButtonStyle}" Margin="0,-4,-4,2" DockPanel.Dock="Right" Width="32" Hei

我的应用程序(使用
MahApps.Metro
)有许多
元素和
Content
,除了
本身的不同属性外,它们都有相同的标记,还有一个
按钮。Content
子元素属性我想通过一个新属性参数化(附加属性?)

我有大约20个按钮的XAML实例:

<Button
    Style="{StaticResource MetroCircleButtonStyle}"
    Margin="0,-4,-4,2"
    DockPanel.Dock="Right"
    Width="32"
    Height="32"
    Name="targetSystemAutoconfigureButton"
    ToolTip="{x:Static me:Resources.Settings_AutoconfigureTargetSystem}"
    Command="{Binding AutoconfigureTargetSystemCommand}"
>
    <Button.Content>
        <Rectangle Fill="{Binding Foreground, ElementName=targetSystemAutoconfigureButton}" Width="12" Height="12">
            <Rectangle.OpacityMask>
                <DrawingBrush Drawing="{StaticResource appbar_magnify}" Stretch="Uniform" />
            </Rectangle.OpacityMask>
        </Rectangle>
    </Button.Content>
</Button>

我已经通过将常量属性移动到派生样式来缩小它:

<!-- In a <ResourceDictionary> located elsewhere -->
<Style x:Key="inputSplitIconButton" TargetType="Button" BasedOn="{StaticResource MetroCircleButtonStyle}">
    <Setter Property="Margin" Value="0,-4,-4,2" />
    <Setter Property="DockPanel.Dock" Value="Right" />
    <Setter Property="Width" Value="32" />
    <Setter Property="Height" Value="32" />
</Style>

<!-- Button XAML is now: -->
<Button
    Style="{StaticResource inputSplitIconButton}"
    Name="targetSystemAutoconfigureButton"
    ToolTip="{x:Static me:Resources.Settings_AutoconfigureTargetSystem}"
    Command="{Binding AutoconfigureTargetSystemCommand}"
>
    <Button.Content>
        <Rectangle Fill="{Binding Foreground, ElementName=targetSystemAutoconfigureButton}" Width="12" Height="12">
            <Rectangle.OpacityMask>
                <DrawingBrush Drawing="{StaticResource appbar_magnify}" Stretch="Uniform" />
            </Rectangle.OpacityMask>
        </Rectangle>
    </Button.Content>
</Button>

但我只想要这个:

<Button
    Style="{StaticResource inputSplitIconButton}"
    Name="targetSystemAutoconfigureButton"
    ToolTip="{x:Static me:Resources.Settings_AutoconfigureTargetSystem}"
    Command="{Binding AutoconfigureTargetSystemCommand}"
    ImageMask="{StaticResource appbar_magnify}"           <--- this property
/>

我会用你的按钮创建一个UserControl

  • 所有按钮xaml都移动到UserControl中
  • 需要动态设置的任何参数都将成为UserControl上的依赖项属性
我想在这个答案中添加示例代码,但我不确定它是否对您有任何好处。希望您现在有一个轻松的时刻,看看这是如何实现的。我已经多次使用此模式来精确解决您所描述的问题,它非常适合

您甚至可以在按钮的内容中插入ContentPresenter控件,并将该控件的
content
属性作为另一个依赖属性公开,以获得绑定乐趣。绑定您喜欢的任何内容:更多文本、矩形等…或者什么都不绑定


请随意发表评论,我很高兴能将其进一步充实…

我找到了一个解决方案,使用一个
DataTemplate
,附加属性将图像名称设置为字符串,使用
IValueConverter
将字符串名称映射到
绘图
对象资源,以绑定到
OpacityMask

感谢这些资源:

Resources.xaml: Window.xaml:

它甚至可以在WPF XAML设计器中工作

我认为这可以通过在
Window.xaml
中使用
{StaticResource appbar\u folder\u ellipsis\u drawing}
来简化,并且只需将其传递给……实验时间到了

更新:简化: 当我意识到
{StaticResource key}
与附加属性一起工作时,我能够进一步简化我的解决方案并消除
StringToStaticResourceConverter

  • Resources.xaml
    中:
  • 删除此行:

  • 还有一个注意事项:我是WPF的常客,这是WPF开发人员工作日大部分时间的绝佳资源。活动通常在欧洲在线时开始,在东海岸回家时开始减少。感谢您的建议和聊天室信息:)
    
    <!-- Note the ordering of elements is important -->
    <me:StringToStaticResourceConverter x:Key="ssr" />
    
    <DataTemplate x:Key="inputSplitIconButtonContentTemplate">
        <Rectangle Fill="{Binding Foreground, RelativeSource={RelativeSource AncestorType=Button}}" Width="12" Height="12">
            <Rectangle.OpacityMask>
                <DrawingBrush Drawing="{Binding Path=(me:Buttons.Image), Mode=OneWay, Converter={StaticResource ssr}, RelativeSource={RelativeSource AncestorType=Button}}" Stretch="Uniform" />
            </Rectangle.OpacityMask>
        </Rectangle>
    </DataTemplate>
    
    <Style x:Key="inputSplitIconButton" TargetType="Button" BasedOn="{StaticResource MetroCircleButtonStyle}">
        <Setter Property="Margin" Value="0,-4,-4,2" />
        <Setter Property="DockPanel.Dock" Value="Right" />
        <Setter Property="Width" Value="32" />
        <Setter Property="Height" Value="32" />
        <Setter Property="TabIndex" Value="10" />
        <Setter Property="ContentTemplate" Value="{StaticResource inputSplitIconButtonContentTemplate}" />
    </Style>
    
    using System;
    using System.Globalization;
    using System.Windows;
    using System.Windows.Data;
    
    namespace MyProject
    {
        public static class Buttons
        {
            public static readonly DependencyProperty ImageProperty = DependencyProperty.RegisterAttached
            (
                name           : "Image",
                propertyType   : typeof(String),
                ownerType      : typeof(Buttons),
                defaultMetadata: new FrameworkPropertyMetadata( defaultValue: null, flags: FrameworkPropertyMetadataOptions.AffectsRender )
            );
    
            public static void SetImage(UIElement element, String value)
            {
                element.SetValue( ImageProperty, value );
            }
    
            public static String GetImage(UIElement element)
            {
                return (String)element.GetValue( ImageProperty );
            }
        }
    
        public class StringToStaticResourceConverter : IValueConverter
        {
            public Object Convert(Object value, Type targetType, Object parameter, CultureInfo culture)
            {
                return Application.Current.FindResource( value );
            }
    
            public Object ConvertBack(Object value, Type targetType, Object parameter, CultureInfo culture)
            {
                return null;
            }
        }
    }
    
    <Button
        Style="{StaticResource inputSplitIconButton}"
        ToolTip="{x:Static me:Resources.Settings_BrowseFile}" 
        me:Buttons.Image="appbar_folder_ellipsis_drawing"
    />