MVVM 和数据绑定示例。
我简单的 Person 类
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
我简单的 PersonViewModel 类
public class PersonViewModel : INotifyPropertyChanged
{
public PersonViewModel(Person person)
{
if (person == null)
throw new ArgumentNullException("person");
this.Model = person;
this.ShowFirstNameCommand = new DelegateCommand((o) => this.showFirstName());
this.ShowLastNameCommand = new DelegateCommand((o) => this.showLastName());
}
public ICommand ShowFirstNameCommand { get; private set; }
public ICommand ShowLastNameCommand { get; private set; }
public Person Model { get; private set; }
public string FirstName
{
get
{
return this.Model.FirstName;
}
set
{
this.Model.FirstName = value;
this.OnPropertyChanged("FirstName");
}
}
public string LastName
{
get
{
return this.Model.LastName;
}
set
{
this.Model.LastName = value;
this.OnPropertyChanged("LastName");
}
}
private string _showString;
public string ShowString
{
get
{
return this._showString;
}
set
{
this._showString = value;
this.OnPropertyChanged("ShowString");
}
}
private void showFirstName()
{
this.ShowString = this.FirstName;
}
private void showLastName()
{
this.ShowString = this.LastName;
}
#region INPC code - can create an abstract base view model class and put this there instead
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
this.OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
}
protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
{
var handler = this.PropertyChanged;
if (handler != null)
{
handler(this, e);
}
}
#endregion
}
使按钮命令起作用的 DelegateCommand 类
// Copyright © Microsoft Corporation. All Rights Reserved.
// This code released under the terms of the
// Microsoft Public License (MS-PL, http://opensource.org/licenses/ms-pl.html.)
using System;
using System.Windows.Input;
namespace WpfApplication1
{
public class DelegateCommand : ICommand
{
/// <summary>
/// Action to be performed when this command is executed
/// </summary>
private Action<object> executionAction;
/// <summary>
/// Predicate to determine if the command is valid for execution
/// </summary>
private Predicate<object> canExecutePredicate;
/// <summary>
/// Initializes a new instance of the DelegateCommand class.
/// The command will always be valid for execution.
/// </summary>
/// <param name="execute">The delegate to call on execution</param>
public DelegateCommand(Action<object> execute)
: this(execute, null)
{
}
/// <summary>
/// Initializes a new instance of the DelegateCommand class.
/// </summary>
/// <param name="execute">The delegate to call on execution</param>
/// <param name="canExecute">The predicate to determine if command is valid for execution</param>
public DelegateCommand(Action<object> execute, Predicate<object> canExecute)
{
if (execute == null)
{
throw new ArgumentNullException("execute");
}
this.executionAction = execute;
this.canExecutePredicate = canExecute;
}
/// <summary>
/// Raised when CanExecute is changed
/// </summary>
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
/// <summary>
/// Executes the delegate backing this DelegateCommand
/// </summary>
/// <param name="parameter">parameter to pass to predicate</param>
/// <returns>True if command is valid for execution</returns>
public bool CanExecute(object parameter)
{
return this.canExecutePredicate == null ? true : this.canExecutePredicate(parameter);
}
/// <summary>
/// Executes the delegate backing this DelegateCommand
/// </summary>
/// <param name="parameter">parameter to pass to delegate</param>
/// <exception cref="InvalidOperationException">Thrown if CanExecute returns false</exception>
public void Execute(object parameter)
{
if (!this.CanExecute(parameter))
{
throw new InvalidOperationException("The command is not valid for execution, check the CanExecute method before attempting to execute.");
}
this.executionAction(parameter);
}
}
}
进入 MainWindow.xaml 的代码。
<StackPanel>
<Button Command="{Binding Path=ShowFirstNameCommand}">Click to show first name</Button>
<Button Command="{Binding Path=ShowLastNameCommand}">Click to show last name</Button>
<TextBox Text="{Binding Path=ShowString}" HorizontalAlignment="Stretch"/>
</StackPanel>
进入 App.xaml.cs 以将其粘合在一起的代码
公共部分类应用程序:应用程序{受保护的覆盖无效OnStartup(StartupEventArgs e){base.OnStartup(e);
var personvm = new PersonViewModel( new Person
{
FirstName = "John",
LastName = "Smith"
});
var window = new MainWindow
{
DataContext = personvm
};
window.Show();
}
}
基本上我在屏幕上显示 2 个按钮和一个文本框。单击时,其中一个按钮将在文本框中显示一个人的名字,另一个按钮将在同一文本框中显示该人的姓氏。如果您检查代码,您将看到我使用 WPF 命令实现了这一点。按钮的 Command 属性绑定到我的 PersonViewModel 类的 ICommand 属性。然后将这些属性“绑定”(使用 DelegateCommand)到同一视图模型类中的私有方法。我还有一个 Public ShowString 属性,它是绑定到屏幕上我的文本框的数据,用于控制文本框中显示的字符串。您将看到我在 viewmodel 类中的私有方法更改了此 ShowString 属性的值,从而更改了文本框中显示的数据。
我的 xaml 代码与您所拥有的不同(您没有提供代码),但这个概念应该适合您。
希望这可以帮助。