MVVM=Model+View+ViewModel
关注点:NotificationObject与数据属性
DelegateCommand与命令属性
命令的传递(单向)
class DelegateCommand : ICommand
{public bool CanExecute(object parameter){if (this.CanExecuteFunc == null){return true;}return this.CanExecuteFunc(parameter);}public event EventHandler CanExecuteChanged;public void Execute(object parameter){if (this.ExecuteAction == null){return;}this.ExecuteAction(parameter);}public Action
ViewModels
//通知Binding属性更新,供ViewModels使用的类
class NotificationObject : INotifyPropertyChanged
{public event PropertyChangedEventHandler PropertyChanged;public void RaisePropertyChanged(string propertyName){if (this.PropertyChanged != null){this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));}}
}
该案例只有一个MainWindow,所以创建一个MainWindowViewModel类
class MainWindowViewModel : NotificationObject
{private double input1;public double Input1{get { return input1; }set{input1 = value;this.RaisePropertyChanged("Input1");}}private double input2;public double Input2{get { return input2; }set{input2 = value;this.RaisePropertyChanged("Input2");}}private double result;public double Result{get { return result; }set{result = value;this.RaisePropertyChanged("Result");}}public DelegateCommand AddCommand { get; set; }public DelegateCommand SaveCommand { get; set; }private void Add(object parameter){this.Result = this.Input1 + this.Input2;}private void Save(object parameter){SaveFileDialog dlg = new SaveFileDialog();dlg.ShowDialog();}public MainWindowViewModel(){this.AddCommand = new DelegateCommand();this.AddCommand.ExecuteAction = new Action(this.Add);this.SaveCommand = new DelegateCommand();this.SaveCommand.ExecuteAction = new Action(this.Save);}
}
主界面
由于Binding不指定Source默认使用了控件的DataContext,所以只需要在MainWindow中增加DataContext,子代控件便可以共享这个DataContext。
public partial class MainWindow : Window
{public MainWindow(){InitializeComponent();this.DataContext = new MainWindowViewModel();}
}
项目使用了Microsoft.Practices.Prism,需要提前引用
要显示单品和饭店信息,所以定义Dish和Restaurant两个类
public class Dish : NotificationObject
{public string Name { get; set; }public string Category { get; set; }public string Comment { get; set; }public double Score { get; set; }
}
class Restaurant : NotificationObject
{public string Name { get; set; }public string Address { get; set; }public string PhoneNumber { get; set; }
}
具有获得菜单和点单服务,先定义相关接口,再实现类
public interface IDataService
{List GetAllDishes();
}
class XmlDataService : IDataService
{public List GetAllDishes(){List dishList = new List();string xmlFileName = System.IO.Path.Combine(Environment.CurrentDirectory, @"Data\Data.xml");XDocument xDoc = XDocument.Load(xmlFileName);var dishes = xDoc.Descendants("Dish");foreach (var d in dishes){Dish dish = new Dish();dish.Name = d.Element("Name").Value;dish.Category = d.Element("Category").Value;dish.Comment = d.Element("Comment").Value;dish.Score = double.Parse(d.Element("Score").Value);dishList.Add(dish);}return dishList;}
}
interface IOrderService
{void PlaceOrder(List dishes);
}
class MockOrderService : IOrderService
{public void PlaceOrder(List dishes){System.IO.File.WriteAllLines(@"C:\Users\cni23287938\Desktop\orders.txt", dishes.ToArray());}
}
因为菜单后面需要具有一个是否选择项,所以要新定义一个DishMenuItemViewModel类
class DishMenuItemViewModel : NotificationObject
{public Dish Dish { get; set; }private bool isSelected;public bool IsSelected{get { return isSelected; }set{isSelected = value;this.RaisePropertyChanged("IsSelected");}}
}
MainWindowViewModel
class MainWindowViewModel : NotificationObject
{private int count;public int Count{get { return count; }set { count = value; this.RaisePropertyChanged("Count"); }}private Restaurant restaurant;public Restaurant Restaurant{get { return restaurant; }set { restaurant = value; this.RaisePropertyChanged("restaurant"); }}private List dishMenu;public List DishMenu{get { return dishMenu; }set { dishMenu = value; this.RaisePropertyChanged("DishMenu"); }}public DelegateCommand PlaceOrderCommand { get; set; }public DelegateCommand SelectMenuItemCommand { get; set; }public MainWindowViewModel(){LoadRestaurant();LoadDishMenu();PlaceOrderCommand = new DelegateCommand(this.PlaceOrderCommandExecute);SelectMenuItemCommand = new DelegateCommand(this.SelectMenuItemExecute);}private void LoadRestaurant(){this.Restaurant = new Restaurant();this.Restaurant.Name = "Crazy";this.restaurant.Address = "北京";this.restaurant.PhoneNumber = "1";}private void LoadDishMenu(){IDataService ds = new XmlDataService();var dishes = ds.GetAllDishes();this.dishMenu = new List();foreach (var dish in dishes){DishMenuItemViewModel item = new DishMenuItemViewModel();item.Dish = dish;this.dishMenu.Add(item);}}private void PlaceOrderCommandExecute(){var selectedDishes = this.dishMenu.Where(i => i.IsSelected == true).Select(i => i.Dish.Name).ToList();IOrderService orderService = new MockOrderService();orderService.PlaceOrder(selectedDishes);MessageBox.Show("订餐成功");}private void SelectMenuItemExecute(){Count = DishMenu.Count(i => i.IsSelected == true);}
}
xaml