wpf 绑定ControlTemplate中的附加属性

wbrvyc0a  于 2023-10-22  发布在  其他
关注(0)|答案(2)|浏览(128)
<Style x:Key="DeckButton_Help" TargetType="{x:Type Button}">
    <Setter Property="Height" Value="22"/>
    <Setter Property="Padding" Value="0,0"/>
    <Setter Property="Margin" Value="0,0"/>
    <Setter Property="Content" Value=""/>
    <Setter Property="local:ButtonProperties.ImageSource" Value=""/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Button}">
                <Button Style="{StaticResource ButtonForeground}" HorizontalContentAlignment="Left" Background="#e1e1e1" BorderBrush="#9d9d9d" 
                        Command="{TemplateBinding Command}" Padding="5,4,0,0" >
                    <Button.Content>
                        <Grid Height="16">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="16"/>
                                <ColumnDefinition Width="*"/>
                            </Grid.ColumnDefinitions>
                            <Image  Style="{StaticResource ButtonImage}" Height="16" Width="16" Source="{TemplateBinding local:ButtonProperties.ImageSource}" 
                                    VerticalAlignment="Center"  HorizontalAlignment="Left" Margin="0,-4,0,0"/>
                            <TextBlock Grid.Column="1" Text="{TemplateBinding Content}" HorizontalAlignment="Center" Margin="5,0,0,0" />
                        </Grid>
                    </Button.Content>
                </Button>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

这里我尝试从外部按钮设置local:ButtonProperties.ImageSource属性。

<Button local:ButtonProperties.ImageSource="/CommonResources;component/bitmap/IDB_BUTTON_HELP.PNG" 
 Style="{StaticResource DeckButton_Help}" Command="{Binding HelpCommand}" Content="Help" Margin="20,0,0,0" Width="65" />

ButtonProperties是这样定义的:

public class ButtonProperties
{
    public static readonly DependencyProperty ImageSourceProperty =
        DependencyProperty.RegisterAttached(
            "ImageSource",
            typeof(string),
            typeof(ButtonProperties),
            new FrameworkPropertyMetadata(null));

    public static string GetImageSource(DependencyObject obj)
    {
        return (string)obj.GetValue(ImageSourceProperty);
    }

    public static void SetImageSource(DependencyObject obj, string value)
    {
        obj.SetValue(ImageSourceProperty, value);
    }
}

问题是图标没有设置,当我调试SetImageSource和GetImageSource没有被调用。

r1wp621o

r1wp621o1#

你可以使用如下所示的常规绑定来代替TemplateBinding。它将提供从字符串到ImageSource的自动类型转换。

<Image ... Source="{Binding RelativeSource={RelativeSource TemplatedParent},
                            Path=(local:ButtonProperties.ImageSource)}"/>

如果你正确设置了图像路径,这应该可以工作(我已经在我的设备上测试了代码)。
然而,将附加属性声明为ImageSource而不是string是有意义的,这样TemplateBinding也可以工作。然后,当您在Button上分配附加属性时,将发生从string到ImageSource的转换,并且附加属性不能包含任何无效字符串。

public class ButtonProperties
{
    public static readonly DependencyProperty ImageSourceProperty =
        DependencyProperty.RegisterAttached(
            "ImageSource",
            typeof(ImageSource),
            typeof(ButtonProperties));

    public static ImageSource GetImageSource(DependencyObject obj)
    {
        return (ImageSource)obj.GetValue(ImageSourceProperty);
    }

    public static void SetImageSource(DependencyObject obj, ImageSource value)
    {
        obj.SetValue(ImageSourceProperty, value);
    }
}

旁注:
1.依赖属性setter和getter中的断点在某些情况下不会被命中,例如。当属性在XAML中设置时。框架直接调用SetValue和GetValue。
1.如果string类型的属性的默认值为null,则无需在属性定义中使用new FrameworkPropertyMetadata(null),也无需在样式定义中使用<Setter Property="local:ButtonProperties.ImageSource" Value=""/>

ymzxtsji

ymzxtsji2#

TemplateBinding不执行自动类型转换,这是您在Binding中所期望的

Source="{TemplateBinding local:ButtonProperties.ImageSource}

其中,源属性的类型为string,目标属性的类型为ImageSource
你必须在附加属性的声明中使用正确的类型:

public class ButtonProperties
{
    public static readonly DependencyProperty ImageSourceProperty =
        DependencyProperty.RegisterAttached(
            "ImageSource",
            typeof(ImageSource),
            typeof(ButtonProperties));

    public static ImageSource GetImageSource(DependencyObject obj)
    {
        return (ImageSource)obj.GetValue(ImageSourceProperty);
    }

    public static void SetImageSource(DependencyObject obj, ImageSource value)
    {
        obj.SetValue(ImageSourceProperty, value);
    }
}

你还得把二传手拿开

<Setter Property="local:ButtonProperties.ImageSource" Value=""/>

因为对于ImageSource类型的属性,空字符串不是有效值。
注意,在XAML中设置ImageSource属性时,不会调用SetImageSource方法。该框架绕过了setter和getter,直接调用SetValueGetValue

相关问题