[源码下载]

重新想象 Windows 8 Store Apps (55) - 绑定: MVVM 模式

作者:webabcd

介绍
重新想象 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 = ; i < ; i++)
{
_products.Add(
new Product
{
ProductId = i,
Name = "Name" + i.ToString().PadLeft(, ''),
Category = "Category" + (char)random.Next(, )
});
}
} 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) + ;
product.Name = name;
product.Category = category; _products.Insert(, 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 = ;
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(, 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
[源码下载]

重新想象 Windows 8 Store Apps (55) - 绑定: MVVM 模式的更多相关文章

  1. 重新想象 Windows 8 Store Apps (52) - 绑定: 与 Element Model Indexer Style RelativeSource 绑定, 以及绑定中的数据转换

    [源码下载] 重新想象 Windows 8 Store Apps (52) - 绑定: 与 Element Model Indexer Style RelativeSource 绑定, 以及绑定中的数 ...

  2. 重新想象 Windows 8 Store Apps (53) - 绑定: 与 ObservableCollection CollectionViewSource VirtualizedFilesVector VirtualizedItemsVector 绑定

    [源码下载] 重新想象 Windows 8 Store Apps (53) - 绑定: 与 ObservableCollection CollectionViewSource VirtualizedF ...

  3. 重新想象 Windows 8 Store Apps (54) - 绑定: 增量方式加载数据

    [源码下载] 重新想象 Windows 8 Store Apps (54) - 绑定: 增量方式加载数据 作者:webabcd 介绍重新想象 Windows 8 Store Apps 之 绑定 通过实 ...

  4. 重新想象 Windows 8 Store Apps 系列文章索引

    [源码下载][重新想象 Windows 8.1 Store Apps 系列文章] 重新想象 Windows 8 Store Apps 系列文章索引 作者:webabcd 1.重新想象 Windows ...

  5. 重新想象 Windows 8 Store Apps (59) - 锁屏

    [源码下载] 重新想象 Windows 8 Store Apps (59) - 锁屏 作者:webabcd 介绍重新想象 Windows 8 Store Apps 之 锁屏 登录锁屏,获取当前程序的锁 ...

  6. 重新想象 Windows 8 Store Apps (15) - 控件 UI: 字体继承, Style, ControlTemplate, SystemResource, VisualState, VisualStateManager

    原文:重新想象 Windows 8 Store Apps (15) - 控件 UI: 字体继承, Style, ControlTemplate, SystemResource, VisualState ...

  7. 重新想象 Windows 8 Store Apps (16) - 控件基础: 依赖属性, 附加属性, 控件的继承关系, 路由事件和命中测试

    原文:重新想象 Windows 8 Store Apps (16) - 控件基础: 依赖属性, 附加属性, 控件的继承关系, 路由事件和命中测试 [源码下载] 重新想象 Windows 8 Store ...

  8. 重新想象 Windows 8 Store Apps (13) - 控件之 SemanticZoom

    原文:重新想象 Windows 8 Store Apps (13) - 控件之 SemanticZoom [源码下载] 重新想象 Windows 8 Store Apps (13) - 控件之 Sem ...

  9. 重新想象 Windows 8 Store Apps (12) - 控件之 GridView 特性: 拖动项, 项尺寸可变, 分组显示

    原文:重新想象 Windows 8 Store Apps (12) - 控件之 GridView 特性: 拖动项, 项尺寸可变, 分组显示 [源码下载] 重新想象 Windows 8 Store Ap ...

随机推荐

  1. [emacs org-mode小技巧] org-indent-mode 让文档更容易阅读

    刚发现Emacs的org-mode里面一个叫做 org-indent-mode 的minor mode对于阅读org-mode文档很不错,版面看起来清晰多了: 从上图可以看到,org-indent-m ...

  2. 申请Payoneer美国万事达信用卡,可获得一个美国虚拟银行账户,立即注册可得25美元

    申请Payoneer美国万事达信用卡,可获得一个美国虚拟银行账户,可以在国内任意一个支持万事达的ATM.POS机上取现和刷卡消费.Payoneer可以网上购物,购买国外的产品,对我们有一个好处就是利用 ...

  3. Sencha Touch+PhoneGap打造超级奶爸之喂养记(一) 源码免费提供

    起源 非常高兴我的宝宝健康平安的出生了.对于初次做奶爸的我,喜悦过后,面临着各中担心,担心宝宝各项指标是否正常.最初几天都是在医院待着,从出生那一天开始,护士妹妹隔一段时间就会来问宝宝的喂奶,大小便, ...

  4. Kafka - 消费接口分析

    1.概述 在 Kafka 中,官方对外提供了两种消费 API,一种是高等级消费 API,另一种是低等级的消费 API.在 <高级消费 API>一文中,介绍了其高级消费的 API 实现.今天 ...

  5. ASP.NET MVC 自定义路由中几个需要注意的小细节

    本文主要记录在ASP.NET MVC自定义路由时,一个需要注意的参数设置小细节. 举例来说,就是在访问 http://localhost/Home/About/arg1/arg2/arg3 这样的自定 ...

  6. (笔记)Linux内核学习(十)之虚拟文件系统概念

    虚拟文件系统 虚拟文件系统:内核子系统VFS,VFS是内核中文件系统的抽象层,为用户空间提供文件系统相关接口: 通过虚拟文件系统,程序可以利用标准Linux文件系统调用在不同的文件系统中进行交互和操作 ...

  7. Spring进阶教程之在ApplicationContext初始化完成后重定义Bean

    前言 很久没有写博客了,也是两个原因:一是自己觉得一直在班门弄斧,其实自己没什么技术可言:二是很多朋友的问题实际上可以自行解决,我经常觉得不该我来过问,或者是有时候我认为技术还得靠自己钻研,我一两句话 ...

  8. 开发者app 上传收集

    直接使用酷传  看各个市场目录 http://publish.coolchuan.com/myaccount/accounts 注册帐号 百度开发者 http://jingyan.baidu.com/ ...

  9. Spark源码系列(八)Spark Streaming实例分析

    这一章要讲Spark Streaming,讲之前首先回顾下它的用法,具体用法请参照<Spark Streaming编程指南>. Example代码分析 val ssc = )); // 获 ...

  10. 天朝专用- 配置pypi镜像

    使用python者,需要经常安装模块,可是身在天朝.pypi.python.org 站点稳定性相当差,为了很更好的使用pip安装模块. 请使用镜像. mac/linux 环境 在用户当前目录下 如没有 ...