【问题标题】:How to Two-way databind a TextBox's Text to a Dependency property如何将文本框的文本双向数据绑定到依赖属性
【发布时间】:2019-11-26 07:13:46
【问题描述】:

我正在尝试将 TextBox 的 Text 属性双向数据绑定到父窗口的依赖属性。

我已经在一个测试项目中将问题缩减到只有几行,以尝试让绑定工作,并且已经在谷歌上搜索了好几天。

来自 Xaml 文件:

<StackPanel>
    <TextBox Text="{Binding A, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}, Mode=TwoWay}" Margin="5"/>
    <TextBox Text="{Binding B, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}, Mode=TwoWay}" Margin="5"/>
    <Button Content="Random" Click="Button_Click" Margin="5"/>
</StackPanel>

以及来自 CS 文件:

public partial class MainWindow : Window
{
    public static readonly DependencyProperty AProperty = DependencyProperty.Register("A", typeof(double), typeof(MainWindow));
    public double A
    {
        get { return (double)GetValue(AProperty); }
        set
        {
            SetValue(AProperty, value);
            SetValue(BProperty, value);
        }
    }

    public static readonly DependencyProperty BProperty = DependencyProperty.Register("B", typeof(double), typeof(MainWindow));
    public double B
    {
        get { return (double)GetValue(BProperty); }
        set
        {
            SetValue(AProperty, value);
            SetValue(BProperty, value);
        }
    }

    public MainWindow()
    {
        InitializeComponent();
        A = 0d;
        B = 1d;
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        A = new Random().Next();
    }
}

当窗口启动时,两个 TextBox 都显示“1”(正如预期的那样,因为构造函数)。单击该按钮会导致两个 TextBox 更新为随机数(也如预期的那样)。

但更改任一 TextBox 中的文本不会更新绑定的依赖属性,因此不会更新另一个 TextBox。

在这些操作过程中没有任何错误消息。

【问题讨论】:

  • 如果你想让 A 设置 B,反之亦然,你应该使用回调。 CLR 包装器的 setter 应该只调用依赖属性本身的 SetValue 而不能做任何其他事情。
  • 为了让文本立即更改回绑定的源属性,还要在绑定中指定UpdateSourceTrigger=PropertyChanged。另请注意,当绑定设置依赖项属性时,WPF 会绕过属性设置器。不要在属性 X 的设置器中调用除 SetValue(XProperty, value); 之外的任何内容。
  • 为了消除这里的一些混乱,您可以将属性 A 和 B 移动到视图模型中,并使用 INotifyPropertyChanged 实现使它们成为常规 CLR 属性。
  • 如果它们都应该是相同的值,为什么你有两个依赖属性而不是一个?
  • @Andy 只是为了看看两个盒子里的效果。实际的应用程序是用户控件中带有多个文本框的计算器,我只是不想从视图模型中创建一个单独的模型。

标签: c# wpf data-binding textbox dependency-properties


【解决方案1】:

如果您希望A 设置B 或反之,则应使用回调。 CLR 包装器的设置器应该调用依赖属性本身的SetValue,而不做任何其他事情,例如:

public static readonly DependencyProperty AProperty = DependencyProperty.Register("A", typeof(double), typeof(MainWindow),
    new PropertyMetadata(new PropertyChangedCallback(OnAChanged)));

public double A
{
    get { return (double)GetValue(AProperty); }
    set { SetValue(AProperty, value); }
}

private static void OnAChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    MainWindow window = (MainWindow)d;
    window.B = window.A;
}

public static readonly DependencyProperty BProperty = DependencyProperty.Register("B", typeof(double), typeof(MainWindow));
public double B
{
    get { return (double)GetValue(BProperty); }
    set { SetValue(BProperty, value); }
}

还请注意,如果您希望为每次击键设置源属性,则应将绑定的UpdateSourceTrigger 属性设置为PropertyChanged。默认情况下,它们将在TextBox 失去焦点时设置。

【讨论】:

  • 都是真的,但是这里的两个依赖属性不是任何Binding的目标属性,而是源属性。将调用 setter。
  • @Clemens:没错。我删除了该部分,因为它与问题无关。
  • OP 也不会严格需要 PropertyChangedCallbacks... 核心问题似乎只是缺少 UpdateSourceTrigger
  • 谢谢,它是 PropertyChangedCallbacks,我不知道设置器中的约定(感谢该文章链接)。我之前已经从我的示例中删除了 UpdateSourceTrigger,因为无论是否存在它都没有影响。
猜你喜欢
  • 2012-07-13
  • 2023-04-06
  • 2012-06-23
  • 1970-01-01
  • 2012-07-11
  • 2016-02-12
  • 1970-01-01
  • 2013-06-21
  • 1970-01-01
相关资源
最近更新 更多