介紹
重新想象 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