简体   繁体   中英

How to Two-way databind a TextBox's Text to a Dependency property

I'm trying to two-way data bind a TextBox's Text property to the parent window's dependency property.

I've trimmed down the problem to just a few lines in a test project to try to get the binding to work, and have been googling around for days.

From the Xaml file:

<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>

and from the CS file:

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();
    }
}

When the window starts, both TextBox's show "1" (as expected because of the constructor). Clicking the button causes both TextBox's to update to a random number (also as expected).

But changing the text in either TextBox does not update the bound dependency property, hence it won't update the other TextBox.

There aren't any error messages during these operations.

If you want A to set B and vice versa, you should use callbacks. The setter of the CLR wrapper should only call SetValue of the dependency property itself and don't do anything else, eg:

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); }
}

Also note that you should set the UpdateSourceTrigger property of the bindings to PropertyChanged if you want the source property to be set for each keystroke. By default, they will be set when the TextBox loses focus.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM