• 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)

  • 相关阅读:
    SAP UI5 formatter的工作原理
    SAP UI5 Negative cache的工作原理
    使用View modification扩展SAP Fiori应用的一个案例
    SAP Fiori应用没能从Fiori Launchpad启动的一个可能原因及分析过程
    使用扩展方式隐藏SAP Fiori应用某个表格标签页的实际案例
    使用Source Monitor检测Java代码的环复杂度
    一个小技巧,快速找出一段ABAP代码里访问到的所有透明表
    如何提取SAP UI5 XML view里定义的字段元素绑定信息(binding path)
    使用扩展技术将SAP Fiori应用隐藏动态创建的UI字段
    使用扩展技术对SAP Fiori应用进行端到端的增强,一个实际案例介绍
  • 原文地址:https://www.cnblogs.com/schbook/p/2619820.html
Copyright © 2020-2023  润新知