从 XAML 绑定到自定义依赖属性

发布于 2024-12-13 15:00:19 字数 2559 浏览 1 评论 0原文

我已经实现了自定义 DependencyProperty 并希望从 XAML 绑定到它。由于某种原因,当更新绑定源(MainWindow.Test)时它不会更新。 绑定源不是 DP,但会触发 PropertyChanged 事件。 但是,该更新适用于非自定义依赖属性

有效

<TextBlock Text="{Binding Test}" />

不起作用

<local:DpTest Text="{Binding Test}"/>

有什么想法吗?


这里是 DP 实现

using System;
using System.Windows;
using System.Windows.Controls;

namespace WpfApplication3
{
public partial class DpTest : UserControl
{
    public DpTest()
    {
        DataContext = this;
        InitializeComponent();
    }

    public string Text
    {
        get { return (string)GetValue(TextProperty); }
        set { SetValue(TextProperty, value); }
    }

    public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(DpTest), new PropertyMetadata(string.Empty, textChangedCallBack));

    static void textChangedCallBack(DependencyObject property, DependencyPropertyChangedEventArgs args)
    {
        int x = 5;
    }
}
}

这里是它的使用方式:

<Window x:Class="WpfApplication3.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:local="clr-namespace:WpfApplication3" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:sys="clr-namespace:System;assembly=mscorlib" Title="MainWindow" Height="350" Width="525">
<StackPanel>
    <TextBlock Text="{Binding Test}"></TextBlock>
    <local:DpTest Text="{Binding Test}"></local:DpTest>
    <Button Click="Button_Click">Update</Button>
</StackPanel></Window>

带有绑定源的代码隐藏:

using System;
using System.Collections.Generic;
using System.Windows;
using System.ComponentModel;

namespace WpfApplication3
{
public partial class MainWindow : Window, INotifyPropertyChanged
{
    public MainWindow()
    {
        DataContext = this;
        InitializeComponent();
    }
    string _test;
    public string Test
    {
        get { return _test; }
        set
        {
            _test = value;
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs("Test"));
            }
        }
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        Test = "Updatet Text";
    }
    public event PropertyChangedEventHandler PropertyChanged;
}
}

I have implemented a custom DependencyProperty and want to bind to it from XAML. For some reason it does not update when the binding source (MainWindow.Test) is updated.
The binding source is no DP but triggers a PropertyChanged event.
The update however works with a non-custom dependency property

Works:

<TextBlock Text="{Binding Test}" />

Does not work:

<local:DpTest Text="{Binding Test}"/>

Any ideas?


Here is the DP implementation:

using System;
using System.Windows;
using System.Windows.Controls;

namespace WpfApplication3
{
public partial class DpTest : UserControl
{
    public DpTest()
    {
        DataContext = this;
        InitializeComponent();
    }

    public string Text
    {
        get { return (string)GetValue(TextProperty); }
        set { SetValue(TextProperty, value); }
    }

    public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(DpTest), new PropertyMetadata(string.Empty, textChangedCallBack));

    static void textChangedCallBack(DependencyObject property, DependencyPropertyChangedEventArgs args)
    {
        int x = 5;
    }
}
}

Here is how it is used:

<Window x:Class="WpfApplication3.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:local="clr-namespace:WpfApplication3" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:sys="clr-namespace:System;assembly=mscorlib" Title="MainWindow" Height="350" Width="525">
<StackPanel>
    <TextBlock Text="{Binding Test}"></TextBlock>
    <local:DpTest Text="{Binding Test}"></local:DpTest>
    <Button Click="Button_Click">Update</Button>
</StackPanel></Window>

Code behind with binding source:

using System;
using System.Collections.Generic;
using System.Windows;
using System.ComponentModel;

namespace WpfApplication3
{
public partial class MainWindow : Window, INotifyPropertyChanged
{
    public MainWindow()
    {
        DataContext = this;
        InitializeComponent();
    }
    string _test;
    public string Test
    {
        get { return _test; }
        set
        {
            _test = value;
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs("Test"));
            }
        }
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        Test = "Updatet Text";
    }
    public event PropertyChangedEventHandler PropertyChanged;
}
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

却一份温柔 2024-12-20 15:00:19

不要不要UserControls上设置DataContext = this;,这样,如果您假设DataContext,则实例上的所有绑定都将失败> 被继承,因为这会阻止它并且也很不可见。在 UserControl 绑定中,您应该为控件命名并执行 ElementName 绑定,或者使用 RelativeSource

例如

<UserControl Name="control" ...>
     <TextBlock Text="{Binding Text, ElementName=control}"/>
<UserControl ...>
     <TextBlock Text="{Binding Text, RelativeSource={RelativeSource AncestorType=UserControl}}"/>

Do not set DataContext = this; on UserControls, that way all bindings on instances will fail if you assume the DataContext to be inherited as this stops it and is quite invisible too. In the UserControl bindings you should either name the control and do ElementName bindings or use RelativeSource.

e.g.

<UserControl Name="control" ...>
     <TextBlock Text="{Binding Text, ElementName=control}"/>
<UserControl ...>
     <TextBlock Text="{Binding Text, RelativeSource={RelativeSource AncestorType=UserControl}}"/>
云巢 2024-12-20 15:00:19

为您的窗口命名并将绑定更改为以下内容:
(否则使用 UserControl 的数据上下文,这不是您想要的)

...
x:Name="mainWindow">
        <Grid>
        <StackPanel>
          <TextBlock Height="20" Background="Yellow" Text="{Binding Test}"></TextBlock>
          <local:DpTest Text="{Binding Path=Test, ElementName=mainWindow, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"></local:DpTest>
          <Button Click="Button_Click">Update</Button>

如果您的 UserControl 中没有绑定,则按以下方式绑定:

<TextBlock Text="{Binding ElementName=dpTest, Path=Text,
Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"></TextBlock>

这对我有用..

HTH

Give your window a name and change your binding to the following:
(otherwise the datacontext of the UserControl is used, which is not what you want in your case)

...
x:Name="mainWindow">
        <Grid>
        <StackPanel>
          <TextBlock Height="20" Background="Yellow" Text="{Binding Test}"></TextBlock>
          <local:DpTest Text="{Binding Path=Test, ElementName=mainWindow, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"></local:DpTest>
          <Button Click="Button_Click">Update</Button>

In you don't have a binding in your UserControl yet then bind the following way:

<TextBlock Text="{Binding ElementName=dpTest, Path=Text,
Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"></TextBlock>

this worked for me..

HTH

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文