如何访问一个Label对象,给定TextBox绑定了它的Content属性
本文关键字:绑定 TextBox 给定 Content 属性 Label 访问 何访问 一个 对象 | 更新日期: 2023-09-27 18:12:47
我的目标是,如果Label
的TextBox
的内容无效,则将Label
的文本包含在错误消息中。在验证过程中,当只有TextBox
对象很容易获得时,我希望获得对Label
对象的引用,该对象的Target
属性绑定到该TextBox
。
BindingOperations.GetBindingExpression()
和相关方法要求目标对象是已知的。
在WPF XAML中我有这个:
<Label Target="{Binding ElementName=RatingTextBox}">_Rating:</Label>
<TextBox Name ="RatingTextBox"/>
在c#代码中,我尝试了这个:
BindingExpression be = RatingTextBox.GetBindingExpression(TextBox.TextProperty);
string format = be.ParentBinding.StringFormat;
然而,上面的be.ParentBinding
是空的,即使我的TextBox
肯定受到标签的约束,因为热键"[Alt]-R"有效。我的TextBox
可以得到Label
的文本不知何故从c#代码背后?
如果我理解正确,您正在寻找一种方法来自动将TextBox
的Tooltip
属性绑定到TextBox
是目标的任何Label
对象的Content
属性。
但是,我可以想到至少两个不同的替代方案,应该达到类似的效果:
- 初始化窗口时,枚举所有的
Label
对象来找到它们的目标,并相应地更新目标的Tooltip
属性。要么显式地设置它们,要么将属性绑定到Label.Content
属性。 - 反转
Label
目标声明的方向。也就是说,创建一个可以在TextBox
对象上使用的附加属性,指示哪个Label
应该针对它。然后使用这个附加属性来初始化Tooltip
属性(例如,在附加属性代码中,绑定或设置Tooltip
属性,或者有一些其他属性也绑定到附加属性,当它改变时,处理绑定或设置)。
在第二个选项中使用附加属性的动机是允许标签/目标关系在XAML中只声明一次(即避免冗余)。只是声明发生在目标对象(即TextBox
)中,而不是标签对象中。
这里有几个例子来说明我的意思& help;
上面第一个选项:
XAML:
<Window x:Class="TestSO32576181BindingGivenSource.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:l="clr-namespace:TestSO32576181BindingGivenSource"
Title="MainWindow" Height="350" Width="525">
<StackPanel>
<StackPanel Orientation="Horizontal">
<Label x:Name="label1" Content="_Label:" Target="{Binding ElementName=textBox1}"/>
<TextBox x:Name="textBox1"/>
</StackPanel>
</StackPanel>
</Window>
c# :
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
InitTooltips(this);
}
private void InitTooltips(FrameworkElement element)
{
foreach (FrameworkElement child in
LogicalTreeHelper.GetChildren(element).OfType<FrameworkElement>())
{
Label label = child as Label;
if (label != null)
{
BindingExpression bindingExpression =
BindingOperations.GetBindingExpression(label, Label.TargetProperty);
if (bindingExpression != null)
{
TextBox textBox =
FindName(bindingExpression.ParentBinding.ElementName) as TextBox;
if (textBox != null)
{
// You could just set the value, as here:
//textBox.ToolTip = label.Content;
// Or actually bind the value, as here:
Binding binding = new Binding();
binding.Source = label;
binding.Path = new PropertyPath("Content");
binding.Mode = BindingMode.OneWay;
BindingOperations.SetBinding(
textBox, TextBox.ToolTipProperty, binding);
}
}
}
InitTooltips(child);
}
}
}
上面第二个选项:
XAML:
<Window x:Class="TestSO32576181BindingGivenSource.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:l="clr-namespace:TestSO32576181BindingGivenSource"
Title="MainWindow" Height="350" Width="525">
<StackPanel>
<StackPanel Orientation="Horizontal">
<!-- Note that the Target property is _not_ bound in the Label element -->
<Label x:Name="label1" Content="_Label:"/>
<!-- Instead, it's specified here via the attached property: -->
<TextBox x:Name="textBox1" l:TooltipHelper.TargetOf="{Binding ElementName=label1}"/>
</StackPanel>
</StackPanel>
</Window>
c# :
static class TooltipHelper
{
public static readonly DependencyProperty TargetOfProperty =
DependencyProperty.RegisterAttached("TargetOf", typeof(Label),
typeof(TooltipHelper), new PropertyMetadata(null, _OnTargetOfChanged));
public static void SetTargetOf(FrameworkElement target, Label labelElement)
{
target.SetValue(TargetOfProperty, labelElement);
}
public static Label GetTargetof(FrameworkElement target)
{
return (Label)target.GetValue(TargetOfProperty);
}
private static void _OnTargetOfChanged(
DependencyObject target, DependencyPropertyChangedEventArgs e)
{
Label oldLabel = (Label)e.OldValue,
newLabel = (Label)e.NewValue;
if (oldLabel != null)
{
BindingOperations.ClearBinding(oldLabel, Label.TargetProperty);
BindingOperations.ClearBinding(target, FrameworkElement.ToolTipProperty);
}
if (newLabel != null)
{
Binding binding = new Binding();
binding.Source = newLabel;
binding.Path = new PropertyPath("Content");
binding.Mode = BindingMode.OneWay;
BindingOperations.SetBinding(
target, FrameworkElement.ToolTipProperty, binding);
binding = new Binding();
binding.Source = target;
binding.Mode = BindingMode.OneWay;
BindingOperations.SetBinding(
newLabel, Label.TargetProperty, binding);
}
}
}
注意,在第二个选项中,不需要在窗口类中添加新代码。它的构造函数可以像往常一样调用InitializeComponent()
,仅此而已。所有的代码隐藏都在TooltipHelper
类中结束,该类在XAML本身中被引用。