C#+XAML的Metro应用开发入门(二)

知识点

1.了解MVVC设计模式中的数据绑定

2.在Metro应用中使用数据绑定,实现一个简单的扑克牌发牌游戏;

一、数据绑定简介

  Metro引用开发沿用了WPF的MVVM设计模式,即Model-View-ViewModel,通过数据和视图的分离实现了UI和功能的松耦合:模型(Model)一般用于封装与应用程序的业务逻辑相关的数据和处理方法;视图(View)则实现了数据的灵活展现方式;视图模型(ViewModel)则作为模型和视图的桥梁,模型通过对视图模型的控制在视图中展现不同的数据。

所谓的数据绑定(Data Banding)是指关联视图(View)与视图模型(ViewModel)的操作,其主要的步骤如下:

  1. 创建一个可察觉类(Observable Class),需要实现InotifyPropertyChanged接口;
  2. 创建一个可察觉集合(Observable Collection),用步骤1所创建的具体类型实例化ObservableCollection<T>;
  3. 设置数据绑定,将创建的可察觉类或可察觉集合绑定到指定的UI元素,可以通过在*.xaml.cs中设置UI元素的DataContext属性,也可以在*.xaml中使用Bingding关键词进行数据绑定;

  以下将通过一个实例说明如何在Metro应用开发中使用数据绑定。

二、在Metro应用中使用数据绑定

  这部分将通过一个简单扑克牌发牌游戏,为大家介绍数据绑定的用法,首先明确这个游戏的基本需求:

  1. 界面包含牌桌和发牌按钮两个元素;
  2. 点击发牌按钮将产生一张随机花色和数字的扑克牌;
  3. 当牌桌上的牌发满后,重新开始发牌;

  创建工程

  打开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)

原文地址:https://www.cnblogs.com/schbook/p/2619820.html