将UserControl绑定到自己的dependencyProperty无法正常工作

4

我有一个问题,即当父级将对象设置为数据绑定时,我无法创建使用自定义对象属性的用户控件。

为了尝试解释我的意思,这里是代码。 自定义对象:

public class MyObj
{
    public string Text { get; set; }

    public MyObj(string text)
    {
        Text = text;
    }
}

用户控件代码后台:

/// <summary>
/// Interaction logic for MyControl.xaml
/// </summary>
public partial class MyControl : UserControl
{
    public static readonly DependencyProperty ObjectProperty =
        DependencyProperty.Register("Object", typeof (MyObj), typeof (MyControl), new PropertyMetadata(default(MyObj)));

    public MyObj Object
    {
        get { return (MyObj) GetValue(ObjectProperty); }
        set { SetValue(ObjectProperty, value); }
    }

    public MyControl()
    {
        InitializeComponent();
    }
}

用户控件 XAML:

<UserControl x:Class="Test.MyControl"
         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="300" d:DesignWidth="300" DataContext="{Binding RelativeSource={RelativeSource Self}}">
<TextBlock Text="{Binding Object.Text}"/>

我希望MyControl显示一个文本块,文本内容为MyObj.Text中的任何字符串;

如果我在代码中添加控件而没有进行任何绑定,则可以正常工作,例如:

MyControl myControl = new MyControl(){ Object = new MyObj("Hello World!") };
grid.Children.Add(myControl);

然而,如果我尝试使用数据绑定,这将不会显示任何内容。以下是MainWindow的代码。
CodeBehind:
public partial class MainWindow : Window, INotifyPropertyChanged
{
    private MyObj _Object;
    public MyObj Object
    {
        get { return _Object; }
        set
        {
            _Object = value;
            OnPropertyChanged("Object");
        }
    }

    public MainWindow()
    {
        InitializeComponent();

        Object = new MyObj("HELLO");
    }

    public event PropertyChangedEventHandler PropertyChanged;

    [NotifyPropertyChangedInvocator]
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }
}

XAML:

请问有没有人能指导我正确的方向,我猜这与在UserControl上使用相对源绑定有关,但我不太确定。

谢谢。

2个回答

17

我个人从未在UserControl上使用过相对自绑定,因此我不确定它是否起作用。您可以尝试设置您的的x:Name,并在绑定中使用它。

<UserControl x:Class="Test.MyControl"
             ...
             x:Name="window">
    <TextBlock Text="{Binding ElementName=window, Path=Object.Text}"/>
</UserControl>
请注意,如果数据绑定在运行时失败,则您还应在“输出”窗口中看到相关的错误消息。

1
太完美了,这个方法非常出色。我以前从未使用过ElementName,从现在开始我会牢记它。谢谢 Will。 - Nick Williams

-1

已经过了很长时间..但由于有一种新技术,我想在这里发布它。

编译时绑定:这是Windows 10引入的一种新类型的绑定。与传统绑定相比,此绑定具有许多性能优势。

而且,额外的好处是您不需要设置任何DataContext,页面或控件本身就是DataContext,您可以将其绑定到页面或控件中的任何内容。

<UserControl x:Class="Test.MyControl"
             ...
             x:Name="window">
    <TextBlock Text="{x:Bind Object.Text}"/>
</UserControl>

但是这是否完美地按照您的想象运作呢?不,不是像您猜测的那样。

编译时绑定默认设置为OneTime,而经典绑定则设置为OneWay

所以您需要明确将模式设置为OneWay,以确保值始终更新。

<UserControl x:Class="Test.MyControl"
             ...
             x:Name="window">
    <TextBlock Text="{x:Bind Object.Text,Mode=OneWay}"/>
</UserControl>

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