如何绑定到另一个 UserControl 中的 UserControl 的属性?
How to bind to properties of a UserControl inside another UserControl?
我有一个显示图标和文本的简单 UserControl
:
<UserControl x:Class="IconLabel"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="26" d:DesignWidth="200" DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<Image x:Name="imgIcon" Source="{Binding Path=IconPath}" Stretch="UniformToFill" Width="26" Height="26" Margin="3,0" />
<Label Content="{Binding Path=LabelText}" Margin="5,0" Grid.Column="1" />
</Grid>
</UserControl>
代码隐藏定义了两个 DependencyProperties
是为了从外部绑定:
Public Class IconLabel
Public Property IconPath As String
Get
Return GetValue(IconPathProperty)
End Get
Set(ByVal value As String)
SetValue(IconPathProperty, value)
End Set
End Property
Public Shared ReadOnly IconPathProperty As DependencyProperty = DependencyProperty.Register("IconPath", GetType(String), GetType(IconLabel), New PropertyMetadata(""))
Public Property LabelText As String
Get
Return GetValue(LabelTextProperty)
End Get
Set(ByVal value As String)
SetValue(LabelTextProperty, value)
End Set
End Property
Public Shared ReadOnly LabelTextProperty As DependencyProperty = DependencyProperty.Register("LabelText", GetType(String), GetType(IconLabel), New PropertyMetadata("LabelText"))
End Class
到目前为止一切正常。我可以在 XAML 中设置它的属性并且它们被正确使用:
<local:IconLabel LabelText="Test"/>
但是,我现在想在另一个 UserControl
中重新使用这个控件,它通过在它旁边显示一个进度条来稍微扩展它的功能(为了示例):
<UserControl x:Class="IconLabelProgress"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:myApp"
mc:Ignorable="d"
d:DesignHeight="26" d:DesignWidth="600" DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="4*" MaxWidth="300"/>
<ColumnDefinition Width="6*"/>
</Grid.ColumnDefinitions>
<local:IconLabel IconPath="{Binding Path=IconPath}" LabelText="{Binding Path=PropName}" />
<ProgressBar Value="{Binding Path=ActualValue}" Minimum="0" Maximum="10" Margin="5" Height="16" VerticalAlignment="Top" Grid.Column="1" />
</Grid>
</UserControl>
使用以下代码隐藏:
Public Class IconLabelProgress
'These are just meant to be passed along to the IconLabel
Public Property IconPath As String
Get
Return GetValue(IconPathProperty)
End Get
Set(ByVal value As String)
SetValue(IconPathProperty, value)
End Set
End Property
Public Shared ReadOnly IconPathProperty As DependencyProperty = DependencyProperty.Register("IconPath", GetType(String), GetType(IconLabelProgress), New PropertyMetadata(""))
Public Property PropName As String
Get
Return GetValue(PropNameProperty)
End Get
Set(ByVal value As String)
SetValue(PropNameProperty, value)
End Set
End Property
Public Shared ReadOnly PropNameProperty As DependencyProperty = DependencyProperty.Register("PropName", GetType(String), GetType(IconLabelProgress), New PropertyMetadata("PropName"))
'This one is new
Public Property ActualValue As Double
Get
Return GetValue(ActualValueProperty)
End Get
Set(ByVal value As Double)
SetValue(ActualValueProperty, value)
End Set
End Property
Public Shared ReadOnly ActualValueProperty As DependencyProperty = DependencyProperty.Register("ActualValue", GetType(Double), GetType(IconLabelProgress), New PropertyMetadata(0.0))
End Class
如果我现在尝试实例化此控件并为内部 IconLabel
控件的标签传入一个值,如下所示:
<local:IconLabelProgress x:Name="ilp1" PropName="Test" ActualValue="5.0" />
然后它不会在其标签上显示 "Test",而是回退到通过 PropertyMetadata("LabelText")
指定的默认值。不过 ActualValue
使用正确。
如何让外部控件将值传递给嵌套控件?
默认情况下(并且您没有指定任何其他内容)绑定是从对象 DataContext
解析的。因此,您的 IconLabel
在 DataContext
.
上搜索名称为 IconPath
的 属性
要指定搜索属性的地方是外部控件,可以在绑定中添加ElementName
并在[=15=上设置名称属性 ] 或者您指定一个 RelativeSource
就像在 How do I use WPF bindings with RelativeSource.
中接受的答案的第二个例子
希望对您有所帮助。
作为一般规则,永远不要像使用
那样显式设置 UserControl 的 DataContext
属性
<UserControl x:Class="IconLabel" ...
DataContext="{Binding RelativeSource={RelativeSource Self}}">
这样做可以有效地防止从 UserControl 的父级继承 DataContext,例如这里
<local:IconLabel LabelText="{Binding Path=PropName}" ... />
其中 PropName
应该是父 DataContext 中的 属性。
与其显式设置 UserControl 的 DataContext
,不如将其 "internal" 绑定写入 RelativeSource
,如
<Label Content="{Binding Path=LabelText,
RelativeSource={RelativeSource AncestorType=UserControl}}" ... />
我有一个显示图标和文本的简单 UserControl
:
<UserControl x:Class="IconLabel"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="26" d:DesignWidth="200" DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<Image x:Name="imgIcon" Source="{Binding Path=IconPath}" Stretch="UniformToFill" Width="26" Height="26" Margin="3,0" />
<Label Content="{Binding Path=LabelText}" Margin="5,0" Grid.Column="1" />
</Grid>
</UserControl>
代码隐藏定义了两个 DependencyProperties
是为了从外部绑定:
Public Class IconLabel
Public Property IconPath As String
Get
Return GetValue(IconPathProperty)
End Get
Set(ByVal value As String)
SetValue(IconPathProperty, value)
End Set
End Property
Public Shared ReadOnly IconPathProperty As DependencyProperty = DependencyProperty.Register("IconPath", GetType(String), GetType(IconLabel), New PropertyMetadata(""))
Public Property LabelText As String
Get
Return GetValue(LabelTextProperty)
End Get
Set(ByVal value As String)
SetValue(LabelTextProperty, value)
End Set
End Property
Public Shared ReadOnly LabelTextProperty As DependencyProperty = DependencyProperty.Register("LabelText", GetType(String), GetType(IconLabel), New PropertyMetadata("LabelText"))
End Class
到目前为止一切正常。我可以在 XAML 中设置它的属性并且它们被正确使用:
<local:IconLabel LabelText="Test"/>
但是,我现在想在另一个 UserControl
中重新使用这个控件,它通过在它旁边显示一个进度条来稍微扩展它的功能(为了示例):
<UserControl x:Class="IconLabelProgress"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:myApp"
mc:Ignorable="d"
d:DesignHeight="26" d:DesignWidth="600" DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="4*" MaxWidth="300"/>
<ColumnDefinition Width="6*"/>
</Grid.ColumnDefinitions>
<local:IconLabel IconPath="{Binding Path=IconPath}" LabelText="{Binding Path=PropName}" />
<ProgressBar Value="{Binding Path=ActualValue}" Minimum="0" Maximum="10" Margin="5" Height="16" VerticalAlignment="Top" Grid.Column="1" />
</Grid>
</UserControl>
使用以下代码隐藏:
Public Class IconLabelProgress
'These are just meant to be passed along to the IconLabel
Public Property IconPath As String
Get
Return GetValue(IconPathProperty)
End Get
Set(ByVal value As String)
SetValue(IconPathProperty, value)
End Set
End Property
Public Shared ReadOnly IconPathProperty As DependencyProperty = DependencyProperty.Register("IconPath", GetType(String), GetType(IconLabelProgress), New PropertyMetadata(""))
Public Property PropName As String
Get
Return GetValue(PropNameProperty)
End Get
Set(ByVal value As String)
SetValue(PropNameProperty, value)
End Set
End Property
Public Shared ReadOnly PropNameProperty As DependencyProperty = DependencyProperty.Register("PropName", GetType(String), GetType(IconLabelProgress), New PropertyMetadata("PropName"))
'This one is new
Public Property ActualValue As Double
Get
Return GetValue(ActualValueProperty)
End Get
Set(ByVal value As Double)
SetValue(ActualValueProperty, value)
End Set
End Property
Public Shared ReadOnly ActualValueProperty As DependencyProperty = DependencyProperty.Register("ActualValue", GetType(Double), GetType(IconLabelProgress), New PropertyMetadata(0.0))
End Class
如果我现在尝试实例化此控件并为内部 IconLabel
控件的标签传入一个值,如下所示:
<local:IconLabelProgress x:Name="ilp1" PropName="Test" ActualValue="5.0" />
然后它不会在其标签上显示 "Test",而是回退到通过 PropertyMetadata("LabelText")
指定的默认值。不过 ActualValue
使用正确。
如何让外部控件将值传递给嵌套控件?
默认情况下(并且您没有指定任何其他内容)绑定是从对象 DataContext
解析的。因此,您的 IconLabel
在 DataContext
.
IconPath
的 属性
要指定搜索属性的地方是外部控件,可以在绑定中添加ElementName
并在[=15=上设置名称属性 ] 或者您指定一个 RelativeSource
就像在 How do I use WPF bindings with RelativeSource.
希望对您有所帮助。
作为一般规则,永远不要像使用
那样显式设置 UserControl 的DataContext
属性
<UserControl x:Class="IconLabel" ...
DataContext="{Binding RelativeSource={RelativeSource Self}}">
这样做可以有效地防止从 UserControl 的父级继承 DataContext,例如这里
<local:IconLabel LabelText="{Binding Path=PropName}" ... />
其中 PropName
应该是父 DataContext 中的 属性。
与其显式设置 UserControl 的 DataContext
,不如将其 "internal" 绑定写入 RelativeSource
,如
<Label Content="{Binding Path=LabelText,
RelativeSource={RelativeSource AncestorType=UserControl}}" ... />