【问题标题】:wpf trouble using dependency properties in a UserControl在 UserControl 中使用依赖属性的 wpf 问题
【发布时间】:2010-11-11 20:08:46
【问题描述】:

我制作了一个用户控件,它打算每隔几秒钟使用来自串行端口的数据更新一次。这个 UserControl 应该非常简单,由一个用于字段名称的标签和另一个包含字段值的标签组成。我说它应该很简单,但它不起作用。它根本不更新,甚至不显示字段名称。

下面是代码:

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

如果我知道要问一个更具体的问题,我会——但谁能告诉我为什么这不起作用?

【问题讨论】:

    标签: wpf user-controls dependency-properties


    【解决方案1】:

    原来在用户控件的 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个小时弄清楚事情。 TNX!
    • 谢谢!简单的修复正是我所需要的。
    【解决方案2】:

    你真的不需要你的用户控件的依赖属性,事实上你应该努力保持用户控件在代码隐藏中没有任何特殊的东西,应该使用自定义控件。

    你应该像这样定义你的 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 挂钩。

    【讨论】:

    • 我喜欢您的解决方案,因为它很简单。但是,我尝试实施它,但没有成功。 LabeledField 的 XAML 看起来完全符合您的建议。后面的代码现在只包含一个调用“InitializeComponents()”的构造函数,这是默认的。 Window1 中的 XAML 如下所示:“” 它给我的错误是“属性在“LabeledField”类型中找不到“fieldName”/“fieldValue”。还有什么建议吗?
    • 您应该有一个业务对象,它公开“field”和“fieldName”属性并将该对象设置为 LabeledField 控件的 DataContext。例如代码中的“public class BusinessObject{public string fieldName { get { return "Text"; } } public int field { get { return 30; } }}",然后在 xaml 中:"
    • 我确实喜欢这个解决方案,但是这个解决方案不太适合那些设计为在同一个 UI 中重复使用/使用多次的用户控件。每个单独的实例都将使用相同的绑定如果开发人员想要将不同的基于字符串的数据推送到给定用户控件的每个实例中怎么办?这种解决方案理论上应该行不通。
    • 如何绑定到没有依赖属性的用户控件属性?我引用收到的错误:System.Windows.Markup.XamlParseException: 'A 'Binding' cannot be set on the 'BranchId' property of type 'BranchFilter'. A 'Binding' can only be set on a DependencyProperty of a DependencyObject.'
    【解决方案3】:

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

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

    【讨论】:

      猜你喜欢
      • 2014-08-31
      • 2013-01-31
      • 2011-06-29
      • 1970-01-01
      • 2011-01-04
      • 1970-01-01
      • 2011-08-07
      • 1970-01-01
      • 2019-04-17
      相关资源
      最近更新 更多