WPF中文网

TemplateBinding模板绑定

TemplateBinding和Binding在使用上类似,但是从它的定义上看,它的Property属性是要求传入一个DependencyProperty依赖属性。

public class TemplateBindingExtension : MarkupExtension
{
    public TemplateBindingExtension();
    public TemplateBindingExtension(DependencyProperty property);

    public DependencyProperty Property { get; set; }
    public IValueConverter Converter { get; set; }
    public object ConverterParameter { get; set; }

    public override object ProvideValue(IServiceProvider serviceProvider);

}

控件的大多数属性都是DependencyProperty类型,所以我们就可以在定制控件的可视化树(控件模板)时,将控件的属性通过TemplateBinding绑定到模板里面的元素的属性上。

我们将前面的例子做一些调整。首先定义一个Person实体类和MainViewModel

public class ObservableObject : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public void RaisePropertyChanged([CallerMemberName] string propertyName = "")
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}
public class Person : ObservableObject
{
    private string name; 
    public string Name
    {
        get { return name; }
        set { name = value;RaisePropertyChanged(); }
    }

    private string occupation;
    public string Occupation
    {
        get { return occupation; }
        set { occupation = value; RaisePropertyChanged(); }
    }

    private int age;
    public int Age
    {
        get { return age; }
        set { age = value; RaisePropertyChanged(); }
    }

    private int money;
    public int Money
    {
        get { return money; }
        set { money = value; RaisePropertyChanged(); }
    }

    private string address;
    public string Address
    {
        get { return address; }
        set { address = value; RaisePropertyChanged(); }
    }
}

MainViewModel

public class MainViewModel : ObservableObject
{
    private Person person;
    public Person Person
    {
        get { return person; }
        set { person = value; RaisePropertyChanged(); }
    }
    public MainViewModel()
    {
        person = new Person()
        {
            Name = "Michael Jackson",
            Occupation = "Musicians",
            Age = 25,
            Money = 9999999,
            Address = "深圳市光明区智慧招商城B4栋5楼"
        };
    }
}

然后,我们在Window的Resource中定义一个Button的样式

<Style x:Key="CardButtonStyle" TargetType="Button">
    <Setter Property="Background" Value="#E7EAF4"/>
    <Setter Property="Foreground" Value="#20232E"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="Button">
                <Border x:Name="border" 
                        Width="{TemplateBinding Width}"
                        Height="{TemplateBinding Height}"
                        Background="{TemplateBinding Background}"
                        BorderThickness="1" 
                        BorderBrush="Gray">
                    <Border.ToolTip>
                        <ContentPresenter/>
                    </Border.ToolTip>
                    <Grid>
                        <Grid.RowDefinitions>
                            <RowDefinition/>
                            <RowDefinition/>
                        </Grid.RowDefinitions>
                        <StackPanel Grid.Row="0" Margin="20">
                            <TextBlock Text="{Binding Name}" 
                                       Foreground="{TemplateBinding Foreground}" 
                                       FontWeight="Bold" FontSize="20"/>
                            <Rectangle Height="5"/>
                            <TextBlock Text="{Binding Occupation}" 
                                       Foreground="{TemplateBinding Foreground}" 
                                       FontSize="16"/>
                        </StackPanel>
                        <StackPanel Grid.Row="1" Orientation="Horizontal">
                            <TextBlock Grid.Column="0" Text="☻"  
                                       VerticalAlignment="Center"  Margin="20" 
                                       FontSize="50" Foreground="#E26441"/>
                            <StackPanel Margin="30 0 0 0" Width="150">
                                <TextBlock Text="COMPANY NAME"/>
                                <TextBlock Text="Age:">
                                    <Run Text="{Binding Age}"/>
                                </TextBlock>
                                <TextBlock Text="Money:">
                                    <Run Text="{Binding Money, StringFormat={}{0:C}}"/>
                                </TextBlock>
                                <TextBlock Text="Address:" TextWrapping="Wrap">
                                    <Run Text="{Binding Address}"/>
                                </TextBlock>
                            </StackPanel>
                        </StackPanel>
                    </Grid>
                </Border>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter Property="Background" Value="#7AAB7D" />
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

在这个样式中,我们定义了一个ControlTemplate控件模板,而控件模板的可视化树稍微有点复杂。首先在最外层定义了一个Border对象,并通过TemplateBinding绑定了Width、Height和Background,这三个属性哪来的?就是Button的Width、Height和Background。ContentPresenter对象则放到了Border的ToolTip属性中。

然后,我们在Border中实例化了一个Grid对象,并在里面放了一些StackPanel和TextBlock,需要注意的是,TextBlock的Text采用了Binding对象,分别绑定了一些属性。这些绑定的数据源其实是从Button的DataContext中获得的。所以我们如果要顺利地使用这个样式,则在使用时,一定要给Button的DataContext属性赋值一个数据源。这个数据源就是Person实体。

前端使用样式的代码

<Button Content="将ControlTemplate定义在Style样式中" 
        Width="280" Height="200" Margin="10" 
        Click="Button_Click"
        Style="{StaticResource CardButtonStyle}"
        DataContext="{Binding Person}">
</Button>

如上所示,我们给Button的DataContext绑定了一个Person数据源,这个Person会在Button的可视化树中被引用,从而得到我们想要的效果。

当鼠标移上去时,还会触发ControlTemplate的触发器,实现背景颜色的变化。

从效果图上看,它像是一个复杂的布局,或者一个UserControl。其实它就是一个Button,只不过,我们通过样式、模板、触发器、绑定等手段,实现了这一效果。

当前课程源码下载:(注明:本站所有源代码请按标题搜索)

文件名:065-《TemplateBinding模板绑定》-源代码
链接:https://pan.baidu.com/s/1yu-q4tUtl0poLVgmcMfgBA
提取码:wpff

——重庆教主 2023年9月28日

copyright @重庆教主 WPF中文网 联系站长:(QQ)23611316 (微信)movieclip (QQ群).NET小白课堂:864486030 | 本文由WPF中文网原创发布,谢绝转载 渝ICP备2023009518号-1