【问题标题】:Template Binding in Control template控件模板中的模板绑定
【发布时间】:2011-06-06 00:59:47
【问题描述】:

我有以下控制模板。

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

但是由于这是按钮控件的控件模板,而按钮控件不是 有源属性,在这种情况下我不能使用 TemplateBinding。

<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>

由于我必须为不同的按钮实例设置不同的图像,因此我也无法对路径进行硬编码。

请告诉我如何解决这种情况。

【问题讨论】:

    标签: wpf xaml data-binding controltemplate templatebinding


    【解决方案1】:

    您还没有真正说明您希望按钮的使用者如何设置源。例如,您可以使用 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 中设置源代码,而不是代码隐藏。此外,标记可能不是一个好主意,因为在控件模板中可能有许多控件,我希望在创建对象时为其设置一些属性。
    • 这不起作用,因为SourceImageSource 类型,而“Temp.jpg”是string。您需要使用转换器将字符串转换为 ImageSource,就像 Image 控件所做的那样。
    【解决方案2】:

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

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

    【讨论】:

      【解决方案3】:

      我建议使用动态资源,例如定义模板如下:

      <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>
      

      【讨论】:

      【解决方案4】:

      TemplateBinding 是一种轻量级的“绑定”,它不支持传统 Binding 的某些功能,例如使用与目标属性关联的已知类型转换器自动进行类型转换(例如将字符串 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>
      

      【讨论】:

      • 除了使用标签之外,还有其他方法吗?我很担心,后来我的控件模板中可能有多个控件,我想在创建对象时设置属性。但是由于标签已经被使用,我将无法再次使用它。
      • 您可以按照 Kent 的建议进行操作。从按钮派生并创建您自己的控件。添加您的自定义依赖属性并像我使用标签一样使用
      • 我的问题与原始帖子略有不同,但这是唯一成功的解决方案。我花了整个上午的时间,因为单个资源字典中的错误阻止了 UI 加载到整个应用程序中的多个 xaml 设计器中。说真的,谢谢。
      猜你喜欢
      • 2020-06-15
      • 1970-01-01
      • 2012-08-18
      • 2011-10-29
      • 2019-10-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多