zoukankan      html  css  js  c++  java
  • 背水一战 Windows 10 (24)

    [源码下载]


    背水一战 Windows 10 (24) - MVVM: 通过 Binding 或 x:Bind 结合 Command 实现,通过非 ButtonBase 触发命令



    作者:webabcd


    介绍
    背水一战 Windows 10 之 MVVM(Model-View-ViewModel)

    • 通过 Binding 或 x:Bind 结合 Command 实现,通过非 ButtonBase 触发命令



    示例
    1、Model
    MVVM/Model/Product.cs

    /*
     * Model 层的实体类,如果需要通知则需要实现 INotifyPropertyChanged 接口
     */
    
    using System.ComponentModel;
    
    namespace Windows10.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(nameof(ProductId));
                }
            }
    
            private string _name;
            public string Name
            {
                get { return _name; }
                set
                {
                    _name = value;
                    RaisePropertyChanged(nameof(Name));
                }
            }
    
            private string _category;
            public string Category
            {
                get { return _category; }
                set
                {
                    _category = value;
                    RaisePropertyChanged(nameof(Category));
                }
            }
            
    
            public event PropertyChangedEventHandler PropertyChanged;
            protected void RaisePropertyChanged(string name)
            {
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs(name));
                }
            }
        }
    }

    MVVM/Model/ProductDatabase.cs

    /*
     * Model 层的数据持久化操作(本地或远程)
     * 
     * 本例只是一个演示
     */
    
    using System;
    using System.Collections.Generic;
    using System.Linq;
    
    namespace Windows10.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);
            }
        }
    }


    2、ViewModel
    MVVM/ViewModel1/MyCommand.cs

    /*
     * 为了方便使用,把 ICommand 再封装一层
     */
    
    using System;
    using System.Windows.Input;
    
    namespace Windows10.MVVM.ViewModel1
    {
        public class MyCommand : ICommand
        {
            // 由 public void Execute(object parameter) 调用的委托
            public Action<object> MyExecute { get; set; }
    
            // 由 public bool CanExecute(object parameter) 调用的委托
            public Func<object, bool> MyCanExecute { get; set; }
    
            public MyCommand(Action<object> execute, Func<object, bool> canExecute)
            {
                this.MyExecute = execute;
                this.MyCanExecute = canExecute;
            }
    
            // 需要发布此事件的话,则调用 RaiseCanExecuteChanged 方法即可
            public event EventHandler CanExecuteChanged;
            public void RaiseCanExecuteChanged()
            {
                if (CanExecuteChanged != null)
                {
                    CanExecuteChanged(this, EventArgs.Empty);
                }
            }
    
            // 用于决定当前绑定的 Command 能否被执行
            // parameter 是由 ButtonBase 的 CommandParameter 传递过来的
            // 如果返回 false 则对应的 ButtonBase 将变为不可用
            public bool CanExecute(object parameter)
            {
                return this.MyCanExecute == null ? true : this.MyCanExecute(parameter);
            }
    
            // 用于执行对应的命令,只有在 CanExecute() 返回 true 时才可以被执行
            // parameter 是由 ButtonBase 的 CommandParameter 传递过来的对象
            public void Execute(object parameter)
            {
                this.MyExecute(parameter);
            }
        }
    }

    MVVM/ViewModel1/ProductViewModel.cs

    /*
     * ViewModel 层
     *
     * 注:为了方便使用,此例对 ICommand 做了一层封装。如果需要了解比较原始的 MVVM 实现请参见 http://www.cnblogs.com/webabcd/archive/2013/08/29/3288304.html
     */
    
    using System;
    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using Windows10.MVVM.Model;
    
    namespace Windows10.MVVM.ViewModel1
    {
        public class ProductViewModel : INotifyPropertyChanged
        {
            // 用于提供 Products 数据
            private ObservableCollection<Product> _products;
            public ObservableCollection<Product> Products
            {
                get { return _products; }
                set
                {
                    _products = value;
                    RaisePropertyChanged(nameof(Products));
                }
            }
    
            // 用于“添加”和“查询”的 Product 对象
            private Product _product;
            public Product Product
            {
                get { return _product; }
                set
                {
                    _product = value;
                    RaisePropertyChanged(nameof(Product));
                }
            }
    
            // 数据库对象
            private ProductDatabase _context = null;
    
            public ProductViewModel()
            {
                _context = new ProductDatabase();
    
                Product = new Product();
                Products = new ObservableCollection<Product>(_context.GetProducts());
            }
    
    
            private MyCommand _getProductsCommand;
            public MyCommand GetProductsCommand
            {
                get
                {
                    return _getProductsCommand ?? (_getProductsCommand = new MyCommand
                      ((object obj) =>
                      {
                          // 从 Model 层获取数据
                          Products = new ObservableCollection<Product>(_context.GetProducts(Product.Name, Product.Category));
                      },
                      null));
                }
            }
    
            private MyCommand _addProductCommand;
            public MyCommand AddProductCommand
            {
                get
                {
                    return _addProductCommand ?? (_addProductCommand = new MyCommand
                      ((object obj) =>
                      {
                          // 在 Model 层添加一条数据
                          Product newProduct = _context.Add(Product.Name, Product.Category);
    
                          // 更新 ViewModel 层数据
                          Products.Insert(0, newProduct);
                      },
                      null));
                }
            }
    
            private MyCommand _updateProductCommand;
            public MyCommand UpdateProductCommand
            {
                get
                {
                    return _updateProductCommand ?? (_updateProductCommand = new MyCommand
                      ((object obj) =>
                      {
                          // 通过 CommandParameter 传递过来的数据
                          Product product = obj as Product;
    
                          // 更新 ViewModel 层数据
                          product.Name = product.Name + "U";
                          product.Category = product.Category + "U";
    
                          // 更新 Model 层数据
                          _context.Update(product);
                      },
                      // 对应 ICommand 的 CanExecute(),如果返回 false 则对应的 ButtonBase 将变为不可用
                      (object obj) => obj != null));
                }
            }
    
            private MyCommand _deleteProductCommand;
            public MyCommand DeleteProductCommand
            {
                get
                {
                    return _deleteProductCommand ?? (_deleteProductCommand = new MyCommand
                      ((object obj) =>
                      {
                          // 通过 CommandParameter 传递过来的数据
                          Product product = obj as Product;
    
                          // 更新 Model 层数据
                          _context.Delete(product);
    
                          // 更新 ViewModel 层数据
                          Products.Remove(product);
                      },
                      // 对应 ICommand 的 CanExecute(),如果返回 false 则对应的 ButtonBase 将变为不可用
                      (object obj) => obj != null));
                }
            }
    
    
            public event PropertyChangedEventHandler PropertyChanged;
            protected void RaisePropertyChanged(string name)
            {
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs(name));
                }
            }
        }
    }


    3、View
    MVVM/View/Demo1_2.xaml

    <Page
        x:Class="Windows10.MVVM.View.Demo1_2"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:Windows10.MVVM.View"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d"
        
        xmlns:Interactivity="using:Microsoft.Xaml.Interactivity" 
        xmlns:Core="using:Microsoft.Xaml.Interactions.Core"
        
        xmlns:vm="using:Windows10.MVVM.ViewModel1">
    
        <Grid Background="Transparent">
            <StackPanel Margin="10 0 10 10">
    
                <!--
                    View 层
                -->
    
                <!--
                    本例通过 Binding 结合 Command 实现 MVVM(用 x:Bind 结合 Command 实现 MVVM 也是一样的),通过非 ButtonBase 触发命令
                -->
    
                <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 Text="{Binding Name}" HorizontalAlignment="Left" />
                                <TextBlock 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 Text="Name:" VerticalAlignment="Center" />
                    <TextBox Name="txtName" Text="{Binding Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Width="100" />
                    <TextBlock Text="Category:" VerticalAlignment="Center" Margin="20 0 0 0" />
                    <TextBox Name="txtCategory" Text="{Binding Category, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Width="100" />
                </StackPanel>
    
                <!--
                    需要引用 Microsoft.Xaml.Interactions.dll 和 Microsoft.Xaml.Interactivity.dll
                
                    Microsoft.Xaml.Interactions.Core:EventTriggerBehavior
                        EventName - 关联的事件名称
                
                    Microsoft.Xaml.Interactions.Core:InvokeCommandAction
                        Command - 指定关联的 ICommand
                        CommandParameter - 传递给 ICommand 的参数
                -->
                <StackPanel Orientation="Horizontal" Margin="0 10 0 0">
                    <TextBlock Text="查询">
                         <Interactivity:Interaction.Behaviors>
                             <Core:EventTriggerBehavior EventName="Tapped">
                                 <Core:InvokeCommandAction Command="{Binding GetProductsCommand}" />
                             </Core:EventTriggerBehavior>
                         </Interactivity:Interaction.Behaviors>
                    </TextBlock>
    
                    <TextBlock Text="添加" Margin="10 0 0 0">
                         <Interactivity:Interaction.Behaviors>
                             <Core:EventTriggerBehavior EventName="Tapped">
                                 <Core:InvokeCommandAction Command="{Binding AddProductCommand}" />
                             </Core:EventTriggerBehavior>
                         </Interactivity:Interaction.Behaviors>
                    </TextBlock>
    
                    <TextBlock Text="更新" Margin="10 0 0 0">
                         <Interactivity:Interaction.Behaviors>
                             <Core:EventTriggerBehavior EventName="Tapped">
                                 <Core:InvokeCommandAction Command="{Binding UpdateProductCommand}" CommandParameter="{Binding SelectedItem, ElementName=listView}"/>
                             </Core:EventTriggerBehavior>
                         </Interactivity:Interaction.Behaviors>
                    </TextBlock>
    
                    <TextBlock Text="删除" Margin="10 0 0 0">
                         <Interactivity:Interaction.Behaviors>
                             <Core:EventTriggerBehavior EventName="Tapped">
                                 <Core:InvokeCommandAction Command="{Binding DeleteProductCommand}" CommandParameter="{Binding SelectedItem, ElementName=listView}"/>
                             </Core:EventTriggerBehavior>
                         </Interactivity:Interaction.Behaviors>
                    </TextBlock>
                </StackPanel>
    
            </StackPanel>
        </Grid>
    </Page>



    OK
    [源码下载]

  • 相关阅读:
    git客户端
    Autowired注解的妙用---在Controller里的构造函数里获取需要注入的对象
    面向对象的理解
    改变对update的做法
    时间戳与日期相互转换
    Git随记
    json数据传输有感
    Mybatis的批量CRUD
    并发与线程有感
    dpkg --info
  • 原文地址:https://www.cnblogs.com/webabcd/p/5679962.html
Copyright © 2011-2022 走看看