将视图的用户控件的绑定源更新为WPF中视图模型的类属性

时间:2018-04-23 14:53:15

标签: c# wpf mvvm binding

我在将某些值从视图更新到viewmodel时遇到问题。我有一个类(ComplexType)实现INotifyPropertyChanged一些属性:

public class ComplexType : INotifyPropertyChanged
{
    private bool enabled = false;
    private string name = "No name";
    private int value = 0;

    public bool Enabled
    {
        get { return this.enabled; }
        set
        {
            if (this.enabled == value) return;
            this.enabled = value;
            this.RaisePropertyChanged();
        }
    }
    public string Name
    {
        get { return this.name; }
        set
        {
            if (this.name == value) return;
            this.name = value;
            this.RaisePropertyChanged();
        }
    }
    public int Value
    {
        get { return this.value; }
        set
        {
            if (this.value == value) return;
            this.value = value;
            this.RaisePropertyChanged();
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected void RaisePropertyChanged([CallerMemberName] string propertyName = null)
    {
        this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

我在ComplexType(来自MvvmLight库的MainViewModel)中使用ViewModelBase

public class MainViewModel : ViewModelBase
{
    private string simpleType1 = "Not set";
    public string SimpleType1
    {
        get { return this.simpleType1; }
        set
        {
            if (this.simpleType1 == value) return;
            this.simpleType1 = value;
            this.RaisePropertyChanged();
        }
    }

    private ComplexType complexType1 = null;
    public ComplexType ComplexType1
    {
        get { return this.complexType1; }
        set
        {
            if (this.complexType1 == value) return;
            this.complexType1 = value;
            this.RaisePropertyChanged();
        }
    }

    private RelayCommand saveCommand;
    public RelayCommand SaveCommand
    {
        get
        {
            return this.saveCommand ?? (this.saveCommand = new RelayCommand(this.ExecuteSaveCommand));
        }
    }
    private void ExecuteSaveCommand()
    {
        Console.WriteLine(this.SimpleType1);
        Console.WriteLine(this.ComplexType1.Value);
    }

    public MainViewModel()
    {
        this.SimpleType1 = "Simple type 1";
        this.ComplexType1 = new ComplexType()
        {
            Enabled = true,
            Name = "Complex type 1",
            Value = 111
        };
    }
}

我想使用用户控件(ComplexControl)来显示ComplexType数据。

XAML:

<UserControl x:Class="MvvmTest.ComplexControl"
             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">
    <StackPanel>
        <CheckBox x:Name="checkbox1"/>
        <TextBlock x:Name="name1TextBlock"/>
        <TextBox x:Name="value1Textbox"/>
    </StackPanel>
</UserControl>

代码背后:

public partial class ComplexControl : UserControl
{
    public static readonly DependencyProperty EnabledProperty =
        DependencyProperty.Register("Enabled", typeof(bool), typeof(ComplexControl),
            new PropertyMetadata(false, new PropertyChangedCallback(ComplexControl.EnabledPropertyChanged)));
    public bool Enabled
    {
        get { return (bool)this.GetValue(ComplexControl.EnabledProperty); }
        set { this.SetValue(ComplexControl.EnabledProperty, value); }
    }
    private static void EnabledPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        ((ComplexControl)d).checkbox1.IsChecked = (bool)e.NewValue;
    }

    public static readonly DependencyProperty ParameterNameProperty =
        DependencyProperty.Register("ParameterName", typeof(string), typeof(ComplexControl),
            new PropertyMetadata("No name", new PropertyChangedCallback(ComplexControl.ParameterPropertyChanged)));
    public string ParameterName
    {
        get { return (string)this.GetValue(ComplexControl.ParameterNameProperty); }
        set { this.SetValue(ComplexControl.ParameterNameProperty, value); }
    }
    private static void ParameterPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        ((ComplexControl)d).name1TextBlock.Text = (string)e.NewValue;
    }

    public static readonly DependencyProperty ValueProperty =
        DependencyProperty.Register("Value", typeof(int), typeof(ComplexControl),
            new PropertyMetadata(0, new PropertyChangedCallback(ComplexControl.ValuePropertyChanged)));
    public int Value
    {
        get { return (int)this.GetValue(ComplexControl.ValueProperty); }
        set { this.SetValue(ComplexControl.ValueProperty, value); }
    }
    private static void ValuePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        ((ComplexControl)d).value1Textbox.Text = ((int)e.NewValue).ToString();
    }

    public ComplexControl()
    {
        InitializeComponent();
    }
}

这是我的MainWindow

XAML:

<Window x:Class="MvvmTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:MvvmTest"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <StackPanel>
        <TextBox x:Name="textbox1" Text="{Binding SimpleType1}"/>
        <local:ComplexControl Enabled="{Binding ComplexType1.Enabled}" ParameterName="{Binding ComplexType1.Name}"
                              Value="{Binding ComplexType1.Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
        <Button Content="Save!" Command="{Binding SaveCommand}"/>
    </StackPanel>
</Window>

代码背后:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = new MainViewModel();
    }
}

数据显示正确,但是当我将绑定的属性更改为ComplexType时,我遇到了问题。例如,如果我在每个文本框中更改SimpleType1ComplexType1.Value文本,然后点击“保存!”按钮,我可以在控制台中看到SimpleType1属性已更新值,但ComplexType1.Value具有初始值。

我试图在StackOverflow上找到答案,但我不能。也许我没有点击关键字。你知道我做错了吗?

1 个答案:

答案 0 :(得分:1)

TextBox中的UserControl应绑定到Value属性:

<TextBox x:Name="value1Textbox" Text="{Binding Value,  RelativeSource={RelativeSource AncestorType=UserControl}}"/>

然而,您在TextBox中输入的值不会传播回源。