知识点
1.了解MVVC设计模式中的数据绑定
2.在Metro应用中使用数据绑定,实现一个简单的扑克牌发牌游戏;
一、数据绑定简介
Metro引用开发沿用了WPF的MVVM设计模式,即Model-View-ViewModel,通过数据和视图的分离实现了UI和功能的松耦合:模型(Model)一般用于封装与应用程序的业务逻辑相关的数据和处理方法;视图(View)则实现了数据的灵活展现方式;视图模型(ViewModel)则作为模型和视图的桥梁,模型通过对视图模型的控制在视图中展现不同的数据。
所谓的数据绑定(Data Banding)是指关联视图(View)与视图模型(ViewModel)的操作,其主要的步骤如下:
- 创建一个可察觉类(Observable Class),需要实现InotifyPropertyChanged接口;
- 创建一个可察觉集合(Observable Collection),用步骤1所创建的具体类型实例化ObservableCollection<T>;
- 设置数据绑定,将创建的可察觉类或可察觉集合绑定到指定的UI元素,可以通过在*.xaml.cs中设置UI元素的DataContext属性,也可以在*.xaml中使用Bingding关键词进行数据绑定;
以下将通过一个实例说明如何在Metro应用开发中使用数据绑定。
二、在Metro应用中使用数据绑定
这部分将通过一个简单扑克牌发牌游戏,为大家介绍数据绑定的用法,首先明确这个游戏的基本需求:
- 界面包含牌桌和发牌按钮两个元素;
- 点击发牌按钮将产生一张随机花色和数字的扑克牌;
- 当牌桌上的牌发满后,重新开始发牌;
创建工程
打开Visual Studio,选择文件〉新建项目,在新建对话框中选择Visual C#模版,建立一个空的应用Blank App(XAML),名称可以自己选择,点击确定即可完成项目的创建。
视图设计
这里采用两行的网格布局(Grid)来安排牌桌和按钮的位置,牌桌使用GridView作为扑克牌的容器,在GridView的ItemTemplate元素中对扑克牌的外观进行定义,最终完成的xaml文件代码如下,其中高亮显示的部分为扑克牌的外观定义:
<Page x:Class="HelloDataBingding.MainPage" IsTabStop="false" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:HelloDataBingding" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}"> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <Border CornerRadius="25" BorderThickness="5" BorderBrush="Brown" Grid.Row="0" Width="900" Height="500" Margin="100,80,100,0" Background="Green"> <GridView x:Name="Table"> <GridView.ItemTemplate> <DataTemplate> <Border Width="150" Height="200" BorderThickness="1" BorderBrush="Black" CornerRadius="15" Margin="10" Background="White"> <Grid> <TextBlock Text="{Binding Number}" HorizontalAlignment="Left" VerticalAlignment="Top" Foreground="{Binding FaceColor}" Margin="10" FontSize="32" FontWeight="Bold"/> <TextBlock Text="{Binding Cluster}" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="{Binding FaceColor}" FontSize="56"/> <TextBlock Text="{Binding Number}" HorizontalAlignment="Right" VerticalAlignment="Bottom" Foreground="{Binding FaceColor}" Margin="10" FontSize="32" FontWeight="Bold"/> </Grid> </Border> </DataTemplate> </GridView.ItemTemplate> </GridView> </Border> <Grid Grid.Row="1"> <Button Width="120" Height="50" Content="发牌" FontSize="24" HorizontalAlignment="Center" VerticalAlignment="Center" Click="OnShuffle"/> </Grid> </Grid> </Page>
视图模型设计
在xaml文件中可以看到,各个UI元素已经被绑定到不同的数据了,而这些数据的定义即来自我们的ViewModel,下面对扑克牌的ViewModel进行设计。
在第一部分中已经指出,ViewModel是一个可察觉类(Observable Class)或可察觉集合(Observable Collection),对一张扑克牌来说,表现为一个可察觉类,对牌桌上的N张扑克牌来说,则表现为一个可察觉集合。
定义一个可察觉集合需要实现InotifyPropertyChanged接口,因此我们定义一个Card类,并让它实现InotifyPropertyChanged接口,为了简单起见,我们为Card赋予了三个属性:number表示牌面的数字、cluster表示牌面的花色、faceColor表示牌的颜色,当这几个属性发生改变时,调用NotifyPropertyChanged方法通知UI及时更新界面。同时,在Card的构造函数中,我们采用随机数构造一张随机数字和花色的牌,最终完成的代码如下:
class Card:INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; private string number; private string cluster; private SolidColorBrush faceColor; public string Number { set { if (number != value) { number = value; NotifyPropertyChanged("Number"); } } get { return number; } } public string Cluster { set { if (cluster != value) { cluster = value; NotifyPropertyChanged("Cluster"); } } get { return cluster; } } public SolidColorBrush FaceColor { set { if (faceColor != value) { faceColor = value; NotifyPropertyChanged("FaceColor"); } } get { return faceColor; } } public Card() { string[] numbers = { "A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K" }; string[] clusters = { "\u2660", "\u2663", "\u2665", "\u2666" }; Random rnd = new Random(); int numberIndex = rnd.Next(0, 12); int clusterIndex = rnd.Next(0,3); this.number = numbers[numberIndex]; this.cluster = clusters[clusterIndex]; if (clusterIndex <= 1) faceColor = new SolidColorBrush(Colors.Black); else faceColor = new SolidColorBrush(Colors.Red); } private void NotifyPropertyChanged(string propertyName) { if (null != PropertyChanged) PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } }
数据绑定
视图与视图模型设计完成之后,它们之间并没有建立联系,需要在视图的xaml.cs文件中设置关联。
我们在MainPage中添加一个可察觉集合(ObservableCollection<T>)cards作为牌桌的视图模型(ViewModel),在OnNavigatedTo方法中通过将牌桌的ItemsSource属性设置为cards来建立它们的关联,而集合中的每个元素则自动与牌桌GridView中的元素GridViewItem关联。
添加事件
最后,我们为发牌按钮添加一个事件,用于在牌桌上生成随机数字和花色的扑克牌,完成的代码如下所示:
private void OnShuffle(object sender, RoutedEventArgs e) { if (cards.Count >= 10) cards.Clear(); else { cards.Add(new Card()); } }
运行效果图
最终的运行效果如下图所示:
运行效果图
当然这个游戏功能非常简单,并不具有任何可玩性,但是读者可以在此基础上对其进行完善,实现一个真正的扑克牌游戏。
(原创文章,转载请注明作者schbook:seekerxu@163.com)