控件模板中的模板绑定

22

我有以下控件模板。

我希望使用模板绑定方式为控件模板中的图像控件设置源属性。

但是,由于这是用于按钮控件的控件模板,并且按钮控件没有源属性,所以在这种情况下我无法使用模板绑定。

<ControlTemplate x:Key="BtnTemplate" TargetType="Button">
        <Border CornerRadius="5"  Margin="15" Cursor="Hand">
            <StackPanel>
                <Image Name="Img" Style="{StaticResource ImageStyle}" Source="temp.jpg" Height="100" Width="100" Margin="5"></Image>
                <Label Content="{TemplateBinding Content}" Background="Transparent" Margin="2"></Label>
            </StackPanel>
        </Border>
    </ControlTemplate>

因为我必须为不同的按钮实例设置不同的图像,所以我也不能硬编码路径。

请告诉我如何处理这种情况。

4个回答

36

我建议使用动态资源,例如按照以下方式定义模板:

<ControlTemplate x:Key="buttonTemplate" TargetType="Button">
    <Border CornerRadius="5"  Margin="15" Cursor="Hand">
        <StackPanel Orientation="Horizontal" Background="Yellow">
            <Image Source="{DynamicResource ResourceKey=Img}" Height="100" Width="100" Margin="5"></Image>
            <Label Content="{TemplateBinding Content}" Background="Transparent" Margin="2"></Label>
        </StackPanel>
    </Border>
</ControlTemplate>

然后像这样使用它:

<Button Content="Button" Template="{StaticResource ResourceKey=buttonTemplate}">
    <Button.Resources>
        <ImageSource x:Key="Img">SomeUri.png/</ImageSource>
    </Button.Resources>
</Button>

1
有没有可能以更简洁的方式使用按钮?例如 <CustomButton Content="Button" Icon="SomeUri.png" />?我被这个问题困扰了,你能帮我吗?http://stackoverflow.com/q/13464735/640607 - Shankar Raju

5

TemplateBinding是一种轻量级的“绑定”,它不支持传统绑定的某些功能,如使用与目标属性关联的已知类型转换器自动进行类型转换(例如将字符串URI转换为BitmapSource实例)。

下面的代码可以正常工作:

<Window x:Class="GridScroll.Window2"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window2">
<Window.Resources>
    <Style TargetType="{x:Type Button}" x:Key="ButtonStyle">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="Button">
                    <Border CornerRadius="5"  Margin="15" Cursor="Hand" Background="Red">
                        <StackPanel Orientation="Horizontal" Background="White">
                            <Image Name="Img" Source="{Binding Path=Tag, RelativeSource={RelativeSource TemplatedParent}}" Margin="5"></Image>
                            <Label Content="{TemplateBinding Content}" Margin="2"></Label>
                        </StackPanel>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>


</Window.Resources>
<StackPanel Orientation="Horizontal">
    <Button Style="{StaticResource ButtonStyle}" Tag="a.jpeg" Content="a"/>
    <Button Style="{StaticResource ButtonStyle}" Tag="b.png" Content="b"/>
</StackPanel>


有没有其他方法可以做到这一点,而不是使用“Tag”?我很担心,因为以后我的控件模板中可能会有多个控件,我想在创建对象时设置属性。但由于“Tag”已经被使用,我将无法再次使用它。 - Sam
你可以按照Kent的建议去做。从按钮派生并创建自己的控件。添加你自定义的依赖属性,并像我使用标签一样使用它。 - biju
我的问题与原帖略有不同,但这是唯一解决问题的方法。我花了整个早上在这个问题上,因为单个资源字典中的错误阻止了应用程序中多个xaml设计师加载UI。真的非常感谢。 - CodeOtaku

3

您并没有说明您希望使用您的按钮的消费者如何设置源。例如,您可以使用 Button.Tag 属性,然后在模板中绑定到它。或者您可以定义自己的控件:

public class ImageButton : Button
{
    // add Source dependency property a la Image
}

然后是模板:

<ControlTemplate TargetType="ImageButton">
    <Border CornerRadius="5"  Margin="15" Cursor="Hand">
        <StackPanel>
            <Image Name="Img" Style="{StaticResource ImageStyle}" Source="{TempateBinding Source}" Height="100" Width="100" Margin="5"></Image>
            <Label Content="{TemplateBinding Content}" Background="Transparent" Margin="2"></Label>
        </StackPanel>
    </Border>
</ControlTemplate>

我使用了标签属性,但它不起作用。Source="{TemplateBinding Tag}",在创建按钮时,Tag="Temp.jpg",但这并不起作用。我希望只在XAML中设置源,而不是在代码后台。此外,Tag可能不是一个好主意,因为控件模板中可能有许多控件,我希望在创建对象时设置一些属性。 - Sam
这样做是行不通的,因为SourceImageSource类型,而 "Temp.jpg" 是一个字符串。你需要使用转换器将字符串转换为 ImageSources, 就像 Image 控件所做的那样。 - Kent Boogaart

1

我不确定我是否很好地理解了你的问题,但为什么不使用ContentPresenter?它允许将图像的代码移动到更高的级别。

<ControlTemplate x:Key="BtnTemplate" TargetType="Button">
  ...
  <ContentPresenter/>
</ControlTemplate>
...
<Button Template="{StaticResource BtnTemplate}">
  <Image .../>
</Button>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接