zoukankan      html  css  js  c++  java
  • WPF MVVM初体验

    首先MVVM设计模式的结构,

    Views: 由Window/Page/UserControl等构成,通过DataBinding与ViewModels建立关联;

    ViewModels:由一组命令,可以绑定的属性,操作逻辑构成;因为View与ViewModel进行了解耦,我们可以对ViewModel进行Unit Test;

    Models:可以是实体对象或者Web服务;

    下面通过一个简单的例子,来介绍一些WPF MVVM模式。示例将展示一个图片浏览器,打开图片,放大/缩小图片大小。首先项目结构:

    UI:

        <Grid>
            <DockPanel>
                <Menu DockPanel.Dock="Top">
                    <Menu>
                        <MenuItem Header="_Open" Command="{Binding OpenFileCommand}"/>
                    </Menu>
                    <Menu>
                        <MenuItem Header="_ZoomIn" Command="{Binding ZoomCommand}" CommandParameter="ZoomIn"/>
                    </Menu>
                    <Menu>
                        <MenuItem Header="_ZoomOut" Command="{Binding ZoomCommand}" CommandParameter="ZoomOut"/>
                    </Menu>
                    <Menu>
                        <MenuItem Header="_Normal" Command="{Binding ZoomCommand}" CommandParameter="Normal"/>
                    </Menu>
                </Menu>
                <ScrollViewer>
                    <Image Source="{Binding ImagePath}" Stretch="None">
                        <Image.LayoutTransform>
                            <ScaleTransform ScaleX="{Binding Zoom}" ScaleY="{Binding Zoom}"/>
                        </Image.LayoutTransform>
                    </Image>
                </ScrollViewer>
            </DockPanel>
        </Grid>

    ViewModelBase(用来实现修改通知):

        public class ViewModelBase : INotifyPropertyChanged
        {
            public event PropertyChangedEventHandler PropertyChanged;
    
            protected virtual void OnPropertyChanged(string propName)
            {
                if(PropertyChanged!=null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs(propName));
                }
            }
        }

    OpenFileCommand:

    public class OpenFileCommand : ICommand
        {
            private MainViewModel _data;
            public OpenFileCommand(MainViewModel data)
            {
                _data = data;
            }
    
            public event EventHandler CanExecuteChanged;
    
            public bool CanExecute(object parameter)
            {
                return true;
            }
    
            public void Execute(object parameter)
            {
                OpenFileDialog dialog = new OpenFileDialog() { Filter = "Image Files|*.jpg;*.png;*.bmp;*.gif" };
    
                if(dialog.ShowDialog().GetValueOrDefault())
                {
                    _data.ImagePath = dialog.FileName;
                }
            }

    ZoomCommand:

        public enum ZoomType
        {
            ZoomIn = 0,
            ZoomOut = 1,
            Normal = 2
        }
    
        public class ZoomCommand : ICommand
        {
            private MainViewModel _data;
    
            public ZoomCommand(MainViewModel data)
            {
                _data = data;
            }
    
            public event EventHandler CanExecuteChanged
            {
                add { CommandManager.RequerySuggested += value; }
                remove { CommandManager.RequerySuggested -= value; }
            }
    
            public bool CanExecute(object parameter)
            {
                return _data.ImagePath != null;
            }
    
            public void Execute(object parameter)
            {
                ZoomType type = (ZoomType)Enum.Parse(typeof(ZoomType), (string)parameter, true);
    
                switch(type)
                {
                    case ZoomType.Normal:
                        _data.Zoom = 1;
                        break;
                    case ZoomType.ZoomIn:
                        _data.Zoom *= 1.2;
                        break;
                    case ZoomType.ZoomOut:
                        _data.Zoom /= 1.2;
                        break;
                }
            }
        }

    MainViewModel:

    public class MainViewModel : ViewModelBase
        {
            private string _imagePath;
    
            public string ImagePath
            {
                get
                {
                    return _imagePath;
                }
                set
                {
                    if (_imagePath != value)
                    {
                        _imagePath = value;
                        OnPropertyChanged("ImagePath");
                    }
                }
            }
    
            private double _zoom = 1.0;
    
            public double Zoom
            {
                get
                {
                    return _zoom;
                }
                set
                {
                    if(_zoom != value)
                    {
                        _zoom = value;
                        OnPropertyChanged("Zoom");
                    }
                }
            }
    
            private ICommand _openFileCommand;
    
            public ICommand OpenFileCommand
            {
                get { return _openFileCommand; }
            }
    
            private ZoomCommand _zoomCommand;
    
            public ZoomCommand ZoomCommand
            {
                get { return _zoomCommand; }
            }
    
            public MainViewModel()
            {
                _openFileCommand = new OpenFileCommand(this);
                _zoomCommand = new ZoomCommand(this);
            }
        }


    下一步我们要做的是将MainViewModel绑定到MainWindow上,我们可以通过下面两种方式绑定:
    1. 直接在MainWindow的Code Behind中进行绑定:

            public MainWindow()
            {
                InitializeComponent();
    
                DataContext = new MainViewModel();
            }

    2. 在App.xaml后台代码中绑定(将App.xaml中StartupUri="MainWindow.xaml"删除掉):

            public App()
            {
                MainWindow window = new MainWindow();
                window.DataContext = new MainViewModel();
                window.Show();
            }

    程序运行效果如下:

    到此为止,这个简单的示例就算完成了。点击这里下载代码。

    感谢您的阅读。

  • 相关阅读:
    ElasticSearch基础4:相关度
    ElasticSearch基础3:全文搜索
    ElasticSearch基础2:查询和过滤初步
    ElasticSearch基础1:初步
    Kafka高级设计和架构,一文深化理解
    JAVA :Jpanel 控件 无法显示问题
    beansbinding NetBeans IDE 中 Swing数据绑定插件
    关于网页游戏断线重连的思路和demo求助
    http://www.classicdosgames.com/
    easyui validatebox 验证集合
  • 原文地址:https://www.cnblogs.com/yang-fei/p/4701946.html
Copyright © 2011-2022 走看看