介紹
重新想象 Windows 8 Store Apps 之 綁定
通過 MVVM 模式實現數據的添 加、刪除、修改和查詢
示例
1、Model 層
Binding/MVVM/Model/ProductDatabase.cs
/* * Model 層的數據持久化操作(本地或遠程) * * 本例只是一個演示 */ using System; using System.Collections.Generic; using System.Linq; namespace XamlDemo.Binding.MVVM.Model { public class ProductDatabase { private List<Product> _products = null; public List<Product> GetProducts() { if (_products == null) { Random random = new Random(); _products = new List<Product>(); for (int i = 0; i < 100; i++) { _products.Add( new Product { ProductId = i, Name = "Name" + i.ToString().PadLeft(4, '0'), Category = "Category" + (char)random.Next(65, 91) }); } } return _products; } public List<Product> GetProducts(string name, string category) { return GetProducts().Where(p => p.Name.Contains(name) && p.Category.Contains(category)).ToList(); } public void Update(Product product) { var oldProduct = _products.Single(p => p.ProductId == product.ProductId); oldProduct = product; } public Product Add(string name, string category) { Product product =new Product(); product.ProductId = _products.Max(p => p.ProductId) + 1; product.Name = name; product.Category = category; _products.Insert(0, product); return product; } public void Delete(Product product) { _products.Remove(product); } } }
Binding/MVVM/Model/Product.cs
/* * Model 層的實體類,如果需要通知則需要實現 INotifyPropertyChanged 接口 */ using System.ComponentModel; namespace XamlDemo.Binding.MVVM.Model { public class Product : INotifyPropertyChanged { public Product() { ProductId = 0; Name = ""; Category = ""; } private int _productId; public int ProductId { get { return _productId; } set { _productId = value; RaisePropertyChanged("ProductId"); } } private string _name; public string Name { get { return _name; } set { _name = value; RaisePropertyChanged("Name"); } } private string _category; public string Category { get { return _category; } set { _category = value; RaisePropertyChanged("Category"); } } public event PropertyChangedEventHandler PropertyChanged; protected void RaisePropertyChanged(string name) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(name)); } } } }
2、ViewModel 層
Binding/MVVM/ViewModel/ProductViewModel.cs
/* * ViewModel 層 */ using System.Collections.ObjectModel; using System.Windows.Input; using XamlDemo.Binding.MVVM.Model; using System.Linq; using System.ComponentModel; namespace XamlDemo.Binding.MVVM.ViewModel { public class ProductViewModel { // 用於提供 Products 數據 public ObservableCollection<Product> Products { get; set; } // 用於“添加”和“查詢”的 Product 對象 public Product Product { get; set; } private ProductDatabase _context = null; public ProductViewModel() { _context = new ProductDatabase(); Product = new Product(); Products = new ObservableCollection<Product>(); } // for 查詢 public ICommand GetProductsCommand { get { return new GetProductsCommand(this); } } public void GetProducts(Product query) { // 從 Model 獲取數據 var products = _context.GetProducts(query.Name, query.Category); // 更新 ViewModel 中的數據 Products.Clear(); foreach (var product in products) { Products.Add(product); } } // for 添加 public ICommand AddProductCommand { get { return new AddProductCommand(this); } } public void AddProduct(Product product) { // 更新 Model var newProduct = _context.Add(product.Name, product.Category); // 更新 ViewModel Products.Insert(0, newProduct); } // for 更新 public ICommand UpdateProductCommand { get { return new UpdateProductCommand(this); } } public void UpdateProduct(Product product) { // 更新 ViewModel product.Name = product.Name + "U"; product.Category = product.Category + "U"; // 更新 Model _context.Update(product); } // for 刪除 public ICommand DeleteProductCommand { get { return new DeleteProductCommand(this); } } public void DeleteProduct(Product product) { // 更新 Model _context.Delete(product); // 更新 ViewModel Products.Remove(product); } } }
Binding/MVVM/ViewModel/AddProductCommand.cs
/* * 添加 Product 數據的 Command */ using System; using System.Windows.Input; namespace XamlDemo.Binding.MVVM.ViewModel { public class AddProductCommand : ICommand { private ProductViewModel _productViewModel; public AddProductCommand(ProductViewModel productViewModel) { _productViewModel = productViewModel; } // parameter 是由 ButtonBase 的 CommandParameter 傳遞過來的 public bool CanExecute(object parameter) { return true; } // 需要發布此事件的話,在 CanExecute() 方法中調用 OnCanExecuteChanged() 方法即可 public event EventHandler CanExecuteChanged; protected virtual void OnCanExecuteChanged(EventArgs e) { if (CanExecuteChanged != null) CanExecuteChanged(this, e); } // parameter 是由 ButtonBase 的 CommandParameter 傳遞過來的 public void Execute(object parameter) { _productViewModel.AddProduct(_productViewModel.Product); } } }
Binding/MVVM/ViewModel/DeleteProductCommand.cs
/* * 刪除 Product 數據的 Command */ using System; using System.Windows.Input; using XamlDemo.Binding.MVVM.Model; namespace XamlDemo.Binding.MVVM.ViewModel { public class DeleteProductCommand : ICommand { private ProductViewModel _productViewModel; public DeleteProductCommand(ProductViewModel productViewModel) { _productViewModel = productViewModel; } // parameter 是由 ButtonBase 的 CommandParameter 傳遞過來的 // 當 ButtonBase 的 CommandParameter 中的數據發生變化時,會執行此方法 // 如果返回 false 則對應的 ButtonBase 將變為不可用 public bool CanExecute(object parameter) { var product = (Product)parameter; if (product == null) return false; return true; } // 需要發布此事件的話,在 CanExecute() 方法中調用 OnCanExecuteChanged() 方法即可 public event EventHandler CanExecuteChanged; protected virtual void OnCanExecuteChanged(EventArgs e) { if (CanExecuteChanged != null) CanExecuteChanged(this, e); } // parameter 是由 ButtonBase 的 CommandParameter 傳遞過來的 public void Execute(object parameter) { var product = (Product)parameter; _productViewModel.DeleteProduct(product); } } }
Binding/MVVM/ViewModel/UpdateProductCommand.cs
/* * 更新 Product 數據的 Command */ using System; using System.Windows.Input; using XamlDemo.Binding.MVVM.Model; namespace XamlDemo.Binding.MVVM.ViewModel { public class UpdateProductCommand : ICommand { private ProductViewModel _productViewModel; public UpdateProductCommand(ProductViewModel productViewModel) { _productViewModel = productViewModel; } // parameter 是由 ButtonBase 的 CommandParameter 傳遞過來的 // 當 ButtonBase 的 CommandParameter 中的數據發生變化時,會執行此方法 // 如果返回 false 則對應的 ButtonBase 將變為不可用 public bool CanExecute(object parameter) { var product = (Product)parameter; if (product == null) return false; return true; } // 需要發布此事件的話,在 CanExecute() 方法中調用 OnCanExecuteChanged() 方法即可 public event EventHandler CanExecuteChanged; protected virtual void OnCanExecuteChanged(EventArgs e) { if (CanExecuteChanged != null) CanExecuteChanged(this, e); } // parameter 是由 ButtonBase 的 CommandParameter 傳遞過來的 public void Execute(object parameter) { var product = (Product)parameter; _productViewModel.UpdateProduct(product); } } }
Binding/MVVM/ViewModel/GetProductsCommand.cs
/* * 獲取 Product 數據的 Command */ using System; using System.Windows.Input; namespace XamlDemo.Binding.MVVM.ViewModel { public class GetProductsCommand : ICommand { private ProductViewModel _productViewModel; public GetProductsCommand(ProductViewModel productViewModel) { _productViewModel = productViewModel; } // parameter 是由 ButtonBase 的 CommandParameter 傳遞過來的 public bool CanExecute(object parameter) { return true; } // 需要發布此事件的話,在 CanExecute() 方法中調用 OnCanExecuteChanged() 方法即可 public event EventHandler CanExecuteChanged; protected virtual void OnCanExecuteChanged(EventArgs e) { if (CanExecuteChanged != null) CanExecuteChanged(this, e); } // parameter 是由 ButtonBase 的 CommandParameter 傳遞過來的 public void Execute(object parameter) { _productViewModel.GetProducts(_productViewModel.Product); } } }
查看本欄目
3、View 層
Binding/MVVM/Demo.xaml
<Page x:Class="XamlDemo.Binding.MVVM.Demo" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:XamlDemo.Binding.MVVM" xmlns:vm="using:XamlDemo.Binding.MVVM.ViewModel" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Grid Background="Transparent"> <StackPanel Margin="120 0 0 0"> <!-- View 層 --> <StackPanel.DataContext> <vm:ProductViewModel /> </StackPanel.DataContext> <ListView Name="listView" ItemsSource="{Binding Products}" Width="300" Height="300" HorizontalAlignment="Left" VerticalAlignment="Top"> <ListView.ItemTemplate> <DataTemplate> <StackPanel Orientation="Horizontal"> <TextBlock FontSize="14.667" Text="{Binding Name}" HorizontalAlignment="Left" /> <TextBlock FontSize="14.667" Text="{Binding Category}" HorizontalAlignment="Left" Margin="10 0 0 0" /> </StackPanel> </DataTemplate> </ListView.ItemTemplate> </ListView> <StackPanel Orientation="Horizontal" Margin="0 10 0 0" DataContext="{Binding Product}"> <TextBlock FontSize="14.667" Text="Name:" VerticalAlignment="Center" /> <TextBox Name="txtName" Text="{Binding Name, Mode=TwoWay}" Width="200" /> <TextBlock FontSize="14.667" Text="Category:" VerticalAlignment="Center" Margin="20 0 0 0" /> <TextBox Name="txtCategory" Text="{Binding Category, Mode=TwoWay}" Width="200" /> </StackPanel> <!-- ButtonBase Command - 指定關聯的命令 CommandParameter - 傳遞給 Command 的參數 --> <StackPanel Orientation="Horizontal" Margin="0 10 0 0"> <Button Name="btnSearch" Content="查詢" Command="{Binding GetProductsCommand}" Margin="10 0 0 0" /> <Button Name="btnAdd" Content="添加" Command="{Binding AddProductCommand}" Margin="10 0 0 0" /> <Button Name="btnUpdate" Content="更新" Command="{Binding UpdateProductCommand}" CommandParameter="{Binding SelectedItem, ElementName=listView}" Margin="10 0 0 0" /> <Button Name="btnDelete" Content="刪除" Command="{Binding DeleteProductCommand}" CommandParameter="{Binding SelectedItem, ElementName=listView}" Margin="10 0 0 0" /> </StackPanel> </StackPanel> </Grid> </Page> <!-- 另外,MVVM Light Toolkit 是目前比較流行的 MVVM 框架,如果需要全 App 純 MVVM 的話可以考慮 在 http://mvvmlight.codeplex.com/ 下載安裝後,手動在安裝目錄的 Vsix 目錄下安 裝相應的 VS 擴展(其中包括 MVVM Light Toolkit 的項目模板) -->
OK
[源碼下載]:http://files.cnblogs.com/webabcd/Windows8.rar