WPF用户控件双向绑定依赖属性

21

我在用户控件中创建了一个依赖属性,但是对用户控件的更改并没有通知到视图模型。

用户控件

<UserControl x:Class="DPsample.UserControl1"
         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">
<Grid>
    <TextBox x:Name="txtName"></TextBox>
</Grid>

用户控件.cs

/// <summary>
/// Interaction logic for UserControl1.xaml
/// </summary>
public partial class UserControl1 : UserControl
{
    public UserControl1()
    {
        InitializeComponent();
    }

    #region SampleProperty 

    public static readonly DependencyProperty SamplePropertyProperty
                                            = DependencyProperty.Register("SampleProperty", 
                                            typeof(string), 
                                            typeof(UserControl1), 
                                            new PropertyMetadata(OnSamplePropertyChanged));


    public string SampleProperty
    {
        get { return (string)GetValue(SamplePropertyProperty); }
        set { SetValue(SamplePropertyProperty, value); }
    }


    static void OnSamplePropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
    {
        (obj as UserControl1).OnSamplePropertyChanged(e);
    }
    private void OnSamplePropertyChanged(DependencyPropertyChangedEventArgs e)
    {
        string SamplePropertyNewValue = (string)e.NewValue;

        txtName.Text = SamplePropertyNewValue;
    }

    #endregion
}

主窗口

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:DPsample" x:Class="DPsample.MainWindow"
    Title="MainWindow" Height="350" Width="525">
<Grid>

    <local:UserControl1 SampleProperty="{Binding SampleText,Mode=TwoWay}" HorizontalAlignment="Left" Margin="76,89,0,0" VerticalAlignment="Top" Width="99"/>
    <Button Content="Show" HorizontalAlignment="Left" Margin="76,125,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click"/>

</Grid>

MainWindow.cs

 public MainWindow()
    {
        InitializeComponent();
        this.DataContext = new MainViewModel();
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        var item = this.DataContext as MainViewModel;
        MessageBox.Show(item.SampleText.ToString());
    }

MainViewModel.cs

public class MainViewModel : NotifyViewModelBase
{
    public MainViewModel()
    {
        this.SampleText = "test";           
    }

    private string _sampleText;
    public string SampleText
    {
        get { return _sampleText; }
        set { _sampleText = value; OnPropertyChanged("SampleText"); }
    }
}

你还没有编写任何代码将 TextBox.Text 属性的更改传递给 SampleProperty。你还应该在那里使用绑定,并添加 RelativeSource={RelativeSource AncestorType=UserControl} - Clemens
@Clemens 我需要为用户控件使用ViewModel吗? - Spen D
不是在这种情况下。然而,UserControl 也可以直接绑定到您的视图模型的 SampleText 属性。那么就根本不需要 SampleProperty 了。 - Clemens
2个回答

64

将用户控件中的 TextBox.Text 属性绑定到其 SampleProperty,代码如下:

<TextBox Text="{Binding SampleProperty,
                RelativeSource={RelativeSource AncestorType=UserControl}}"/>

现在,您可以简单地删除 OnSamplePropertyChanged 回调函数。


您还可以像这样默认注册SampleProperty进行双向绑定:

public static readonly DependencyProperty
    SamplePropertyProperty = DependencyProperty.Register(
        "SampleProperty", typeof(string), typeof(UserControl1),
        new FrameworkPropertyMetadata(
            null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));

11
难以置信我已经阅读了那么多有关自定义UserControl和DependencyProperty的教程和示例,但没有一个提到FrameworkPropertyMetadata,它解决了将值传回模型的问题。做得好! - Diogo Mendonça

4

另一种方法是使用ElementName绑定。首先为UserControl分配x:Name属性(例如x:Name="MyUC"),然后将绑定更改为:

<TextBox Text="{Binding ElementName=MyUC, Path=SampleProperty}"/>

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