WPF中使用依赖属性在UserControl中出现问题

8

我创建了一个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>

以下是引用用户控件的窗口的XAML。首先是标题:
```xml

这是引用用户控件的窗口的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">

然后是用户控件本身:
<me:LabeledField fieldName="Test" Width="200" Height="30" fieldValue="{Binding businessObjectField}"/>

如果我知道更具体的问题需要问什么,我会去问。但是有人能告诉我为什么这个不起作用吗?
3个回答

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}" />

终于!花了5个小时才搞明白。谢谢! - zdrsh
谢谢!简单的修复就是我所需要的。 - dex3703

5

如果您想绑定控件的属性,应在绑定中指定。如果源未明确指定,则绑定相对于DataContext进行评估,因此您的绑定不会绑定到控件,而是绑定到继承的上下文(该上下文可能缺少您要绑定到的属性)。您需要的是:

<Label Width="100" Height="30" Name="fieldValueLabel"
       Content="{Binding Path=fieldValue, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type DAS1.LabeledField}}}" />

4

您的用户控件真的不需要一个依赖属性,事实上,您应该努力保持用户控件在代码后台没有任何特殊内容,自定义控件应该用于此目的。

您应该像这样定义您的用户控件(没有任何代码后台):

<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挂钩。


我喜欢你的解决方案,因为它很简单。然而,我尝试实现它却没有成功。LabeledField的XAML看起来和你建议的一模一样。现在代码后台只包含一个构造函数,它调用了“InitializeComponents()”,这是默认设置。Window1的XAML如下所示:“<me:LabeledField fieldName ="Test" fieldValue="{Binding point.lat}" Width="200" Height="30" />”,但是它给我报错,说“在类型'LabeledField'中找不到属性'fieldName'/'fieldValue'”。还有其他建议吗? - Klay
你应该有一个业务对象,它暴露了"field"和"fieldName"属性,并将该对象设置为LabeledField控件的DataContext。例如,在代码中定义一个类:"public class BusinessObject{public string fieldName { get { return "Text"; } } public int field { get { return 30; } }}",然后在XAML中:<DAS1:LabeledField DataContext="{Binding */在此处设置对象路径*/}"/> - Kenan E. K.
3
我喜欢这个解决方案,但它不适用于旨在在同一 UI 中多次重复使用/消耗的用户控件。每个实例都将使用相同的绑定,如果开发人员想要将不同的基于字符串的数据推送到给定用户控件的每个实例中,该怎么办?理论上,这个解决方案不应该起作用。 - IbrarMumtaz
你如何在不使用依赖属性的情况下绑定到用户控件属性?我引用我收到的错误:“System.Windows.Markup.XamlParseException:'无法在类型为'BranchFilter'的'BranchId'属性上设置'Binding'。'Binding'只能在DependencyObject的DependencyProperty上设置。” - ProfK

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接