WPF之ElementName,Source,RelativeSource绑定🔥

1/23/2024 WPF

在WPF(Windows Presentation Foundation)中,ElementName,Source和RelativeSource是用于在XAML中进行数据绑定的重要属性和对象。

# ElementName

ElementName属性允许你将数据绑定目标设置为XAML中具有指定名称的另一个元素。你可以使用该属性来引用XAML中同一命名范围内的元素,以便在数据绑定中使用它们。这个属性通常用于在不同控件之间进行数据绑定。

<TextBox x:Name="textBox1" Text="{Binding TextValue}" />
<Label Content="{Binding Text, ElementName=textBox1}" />
1
2

# Source

Source属性允许你直接指定数据绑定的源对象实例。通常用于当你知道要绑定的对象的实例时,你可以直接使用该属性。这个属性不仅可以用于绑定到数据对象,也可以用于绑定到资源对象。

# 1、静态成员或属性

你可以使用 x:Static 扩展来指定一个静态成员或属性作为数据绑定的源。

<TextBox Text="{Binding Path=Name}" Source="{x:Static local:Person.DefaultPerson}" />
1

在这里,local:Person.DefaultPerson 表示引用了Person类的 DefaultPerson 静态属性作为数据绑定的源。因此,TextBox 的文本内容将根据Person.DefaultPerson 的值来动态显示。其文本内容通过数据绑定与 Person.DefaultPerson 的 Name 属性关联起来,使得 TextBox 的文本内容能够动态地显示 Person.DefaultPerson 的名字。

# 2、命名资源

你可以使用 {StaticResource} 或 {DynamicResource} 扩展来引用命名资源,其中 {StaticResource} 用于引用静态资源,而 {DynamicResource} 用于引用动态资源。

<TextBox Text="{Binding Path=Name}" Source="{StaticResource DefaultPerson}" />
1

在这个示例中,DefaultPerson 是一个在 XAML 中命名的静态资源。

# 3、常量值

如果你希望指定一个常量值作为数据绑定的源,你可以直接在大括号中写入常量值。

<TextBox Text="{Binding Path=Name}" Source="{x:Static local:Constants.DefaultPerson}" />
1

在这个示例中,Constants.DefaultPerson 可以是一个常量值,它作为数据绑定的源。

# 4、静态方法

有时你可能需要调用一个静态方法来获取数据绑定的源,你可以使用 {x:Static} 扩展来调用静态方法。

<TextBox Text="{Binding Path=Name}" Source="{x:Static local:Utility.GetDefaultPerson}" />
1

在这个示例中,Utility.GetDefaultPerson 表示调用 Utility 类的 GetDefaultPerson 静态方法,该方法返回数据绑定的源。

# RelativeSource

RelativeSource 是 WPF 中用于相对于当前元素查找绑定源的属性。它提供了一种动态的绑定方式,可以相对于当前元素的父级、祖先、兄弟等来确定绑定源。以下是 RelativeSource 的几种常见用法:

# 1、Self

用于将数据绑定的源设置为当前元素本身。

<TextBox Text="{Binding Path=Name, RelativeSource={RelativeSource Self}}" />
1

在这个示例中,TextBox 的 Text 属性通过数据绑定与自身的 Name 属性关联起来。

# 2、AncestorType

用于相对于当前元素查找指定类型的祖先元素,并将其作为数据绑定的源。

<TextBox Text="{Binding DataContext.Name, RelativeSource={RelativeSource AncestorType=Window}}" />
1

在这个示例中,TextBox 的 Text 属性通过数据绑定与其所在的 Window 元素的 DataContext 中的 Name 属性关联起来。

# 3、AncestorLevel

用于指定相对于当前元素的第几级祖先元素,并将其作为数据绑定的源。

<Window x:Class="MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:YourNamespace"
        Title="MainWindow" Height="450" Width="800">
    <StackPanel>
        <TextBox Text="{Binding Name}" />
        <StackPanel>
            <TextBox Text="{Binding DataContext.Name, RelativeSource={RelativeSource AncestorLevel=2}}" />
        </StackPanel>
    </StackPanel>
</Window>
1
2
3
4
5
6
7
8
9
10
11
12

在这个示例中,我们在 MainWindow 的 StackPanel 中嵌套了另一个 StackPanel。第一个 StackPanel 的 DataContext 是 Person 对象,因此第一个 TextBox 直接绑定到 Person 对象的 Name 属性。 第二个 TextBox 使用 AncestorLevel=2 来指定相对于当前元素的第二级祖先元素,即 MainWindow。这样,它就能访问 MainWindow 的 DataContext 中的 Person 对象的 Name 属性。 通过这种方式,我们可以使用 AncestorLevel 来访问位于嵌套结构中较远祖先元素的数据。

# 4、TemplatedParent

用于将数据绑定的源设置为控件模板中的父级元素(即使用该模板的控件)。

<Style TargetType="local:MyButton">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="local:MyButton">
                <Border Background="{TemplateBinding Background}"
                        BorderBrush="{TemplateBinding BorderBrush}"
                        BorderThickness="{TemplateBinding BorderThickness}"
                        Padding="{TemplateBinding Padding}">
                    <TextBlock Text="{TemplateBinding Content}" 
                               Foreground="{Binding Foreground, RelativeSource={RelativeSource TemplatedParent}}"
                               HorizontalAlignment="Center"
                               VerticalAlignment="Center" />
                </Border>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter TargetName="textBlock" Property="Foreground" Value="Red" />
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

在这个示例中,我们定义了一个名为 MyButton 的自定义按钮控件,它的模板中包含一个 TextBlock 控件来显示按钮的文本。在 TextBlock 的 Foreground 属性中,我们使用了 TemplatedParent 来绑定到 MyButton 控件的 Foreground 属性,以便按钮的文本颜色能够继承按钮的前景色。 然后,我们使用 ControlTemplate.Triggers 来定义一个触发器,在按钮的 IsMouseOver 属性为 True 时,将 TextBlock 控件的 Foreground 属性设置为红色,实现了按钮悬停时文本颜色变为红色的效果。