我创建了一个UserControl,意味着每隔几秒就会使用串行端口的数据更新一次。此UserControl应该非常简单,包含字段名称的Label和包含字段值的另一个Label。我说它应该很简单,但它不起作用。它根本不更新,甚至不显示字段名称。
以下是代码:
public partial class LabeledField : UserControl {
public LabeledField() {
InitializeComponent();
}
public string fieldName {
get { return fieldNameLabel.Content.ToString(); }
set { fieldNameLabel.Content = value; }
}
public string fieldValue {
get { return (string)GetValue(fieldValueProperty); }
set { SetValue(fieldValueProperty, value); }
}
public static readonly DependencyProperty fieldValueProperty =
DependencyProperty.Register(
"fieldValue",
typeof(string),
typeof(LabeledField),
new FrameworkPropertyMetadata(
"No Data"
)
)
;
}
这是XAML:
<UserControl x:Class="DAS1.LabeledField" Name="LF"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<StackPanel Orientation="Horizontal">
<Label Width="100" Height="30" Background="Gray" Name="fieldNameLabel" />
<Label Width="100" Height="30" Background="Silver" Name="fieldValueLabel" Content="{Binding fieldValue}" />
</StackPanel>
以下是引用UserControl的Window的XAML。首先是标题:
<Window x:Class="DAS1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:me="clr-namespace:DAS1"
Title="Window1" Height="580" Width="780">
然后是UserControl本身:
<me:LabeledField fieldName="Test" Width="200" Height="30" fieldValue="{Binding businessObjectField}"/>
如果我知道要提出更具体的问题,我会 - 但有人可以告诉我为什么这不起作用吗?
答案 0 :(得分:9)
事实证明,在用户控件的XAML中,未正确指定绑定。
原来是:
<Label Width="100" Height="30" Name="fieldValueLabel" Content="{Binding fieldValue}" />
但我没有指定fieldValue所属的元素。它应该是(假设我的用户控件名为“LF”:
<Label Width="100" Height="30" Name="fieldValueLabel" Content="{Binding ElementName=LF, Path=fieldValue}" />
答案 1 :(得分:5)
如果要绑定到控件的属性,则应在绑定中指定。如果未明确指定其源,则绑定将相对于DataContext
进行评估,因此绑定不会绑定到您的控件,而是绑定到继承的上下文(可能缺少您绑定的属性)。你需要的是:
<Label Width="100" Height="30" Name="fieldValueLabel"
Content="{Binding Path=fieldValue, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type DAS1.LabeledField}}}" />
答案 2 :(得分:4)
你真的不需要你的用户控件的依赖属性,事实上你应该努力保持用户控件没有任何特殊的代码隐藏,应该使用自定义控件。
你应该像这样定义你的UserControl(没有任何代码):
<UserControl x:Class="DAS1.LabeledField"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<StackPanel Orientation="Horizontal">
<Label Width="100" Height="30" Name="fieldNameLabel" Content="{Binding fieldName}" />
<Label Width="100" Height="30" Name="fieldValueLabel" Content="{Binding field}" />
</StackPanel>
然后,确保您的业务对象实现了INotifyPropertyChanged,因为您无法有效地更新业务对象,而无需至少修改它。 fieldName
只是一个示例,说明如何将标签上的显示名称自动绑定到业务对象上的属性。
然后,只需确保UserControl的DataContext是您的业务对象。
这将如何运作? Label.Content属性是DependencyProperty,它将支持绑定本身。您的业务对象实现了INotifyPropertyChanged,因此支持绑定更新 - 没有它,绑定系统在您的字段值更改时不会得到通知,无论您是将其绑定到一端的DependencyProperty 。
如果要在其他地方重用此用户控件,只需将业务对象的所需实例放置到所需LabeledField控件的DataContext中。绑定将自己与DataContext挂钩。