了解ViewModel中的数据绑定

时间:2016-03-16 12:59:39

标签: c# wpf xaml mvvm

我是C#/ .NET的新手,特别是对于绑定,因为对我来说这是一个新概念,我确实理解下面的简单绑定......

<TextBox Name="myTextField" Text="{Binding Path=Text, ElementName=myTextField2}" />
<TextBox Name="myTextField2" Text="{Binding Path=Text, ElementName=myTextField}"/>

但是我对如何从ViewModel感到困惑。我watching a video关于MVVM这帮助我了解了一些我理解不了的概念,但由于没有提供代码,我试着编写代码以查看实际演示,但我是错过了XAML/Binding部分,因为演示者没有显示该部分代码。您可以在分钟5:05中查看所有内容的工作原理。

以下是所有代码:

人类:

using System.ComponentModel;
using System.Runtime.CompilerServices;

namespace MVVM_BestPractices 
{
    public class Person : INotifyPropertyChanged 
    {
        private string _firstName;
        public string FirstName 
        {
            get { return _firstName; }
            set 
            {
                _firstName = value;
                OnPropertyChanged();
                OnPropertyChanged("FullName");
            }
        }

        private string _lastName;
        public string LastName 
        {
            get { return _lastName; }
            set 
            {
                _lastName = value;
                OnPropertyChanged();
                OnPropertyChanged("FullName");
            }
        }

        public string FullName 
        {
            get { return string.Format("{0} {1}", this.FirstName, this.LastName); }
        }

        public Person() {}

        public Person(string firstName, string lastName) 
        {
            this.FirstName = firstName;
            this.LastName = lastName;
        }

        // INotifyPropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged([CallerMemberName] string propertyName = "") 
        {
            var handler = PropertyChanged;
            if (handler != null)
                handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

ViewModel类:

using System.ComponentModel;
using System.Runtime.CompilerServices;

namespace MVVM_BestPractices {
    public class ViewModel : INotifyPropertyChanged
    {
        Person _model;
        public Person Model 
        {
            get { return _model; }
            set 
            {
                _model = value;
                OnPropertyChanged();
            }
        }

        public ViewModel() 
        {
            Model = new Person("Brian", "Lagunas");
        }

        // INotifyPropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged([CallerMemberName] string propertyName = "") 
        {
            var handler = PropertyChanged;
            if (handler != null)
                handler(this, new PropertyChangedEventArgs(propertyName));
        }

    }
}

XAML代码:正如您所看到的,我不知道如何绑定ViewModel中的数据。

<Window x:Class="MVVM_BestPractices.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:MVVM_BestPractices"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Window.DataContext>
        <local:ViewModel/>
    </Window.DataContext>
    <Grid>
        <TextBox  Width="200" Height="30" Margin="158,57,159,233"/>
        <TextBox  Width="200" Height="30" Margin="158,102,159,188"/>
        <TextBlock Text="{Binding Person, Mode=OneWay}" Width="200" Height="30" Margin="158,148,159,142"/>
    </Grid>
</Window>

有人可以帮我将ViewModel中的数据绑定到textBoxes,如分钟5:05所示?

这有助于我理解BindingMVVM

3 个答案:

答案 0 :(得分:3)

不看视频,我会说:

<TextBox  Text={Binding Model.FirstName} ... />
<TextBox  Text={Binding Model.LastName} ... />
<TextBlock Text="{Binding Model.FullName, Mode=OneWay}" ... />

这应该有效但只是因为你在这里的Model类上实现了INotifyPropertyChanged。你并不总是拥有或想要那样。

附注:尽量避免使用Margin=""进行布局。我知道设计师所做的事情,但这是一个非常糟糕的做法。

答案 1 :(得分:2)

在ViewModel中,您调用属性Model,而不是Person(Person是您的类型)。因此,您需要将绑定更改为{Binding Model, Mode=OneWay}。然后会发生绑定,但你不会得到你想要的结果(我猜)。你想要写的不是Model的值(即Model.ToString()),而是Model的FullName属性的值。所以这很简单:{Binding Model.FullName, Mode=OneWay}

此外,在您的属性集中,您应该首先检查新值是否与旧值不同。

set
{
    if (_firstName == value) return;
    _firstName = value;
    OnPropertyChanged();
    OnPropertyChanged(nameof(FullName)); // And use nameof() like this if you're in C# 6
}

答案 2 :(得分:1)

如果已设置DataContext(您拥有),则可以直接绑定到ViewModel中的Model属性:

<TextBlock Text="{Binding Person, Path=FirstName}"/>

或者您可以省略路径:

<TextBlock Text="{Binding Person.FirstName}"/>