wpf中使用MVVM模式进行开发,View与ViewModule的交互个人总结(转)

在MVVM模式中,viewer负责向用户展示软件设计意图,以期获得最佳的用户体验。VM则负责实现(一定的)业务逻辑,响应Viewer要求,达到隔离业务逻辑的目的。在实际开发中,两者如何进行交互往往是比较头痛的事情。现将开发中用到的交互方法总结一下:
一、使用Binding Command
    利用Command是最常用的手段,因为在软件设计中,软件功能的触发往往是由一些具有Command属性的控件实现的,比如buttonbase、meumItem。在这里推荐一种比较实用的ICommand,代码如下:
该Command可以在响应命令前通过CanExecute方法判断是否该命令有效。但是这种command只适用于具有Command属性的ElementFrame。如果没有,则不能进行Binding。

public class RelayCommand<T> : ICommand
    {
        #region Fields

        readonly Action<T> _execute = null;
        readonly Predicate<T> _canExecute = null;

        #endregion

        #region Constructors
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="execute"> 执行逻辑,实际执行函数</param>
        public RelayCommand(Action<T> execute)
            : this(execute, null)
        {
        }
        public RelayCommand(Action<T> execute, Predicate<T> canExecute)
        {
            if (execute == null)
                throw new ArgumentNullException("execute");

            _execute = execute;
            _canExecute = canExecute;
        }

        #endregion

        #region ICommand Members
        public bool CanExecute(object parameter)
        {
            return _canExecute == null ? true : _canExecute((T)parameter);
        }

        public event EventHandler CanExecuteChanged
        {
            add
            {
                if (_canExecute != null)
                    CommandManager.RequerySuggested += value;
            }
            remove
            {
                if (_canExecute != null)
                    CommandManager.RequerySuggested -= value;
            }
        }

        public void Execute(object parameter)
        {
            _execute((T)parameter);
        }

        #endregion
    }

    /// <summary>
    /// 
    /// </summary>
    public class RelayCommand : ICommand
    {
        #region Fields

        readonly Action _execute;
        readonly Func<bool> _canExecute;

        #endregion

        #region Constructors

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="execute">实际执行函数</param>
        public RelayCommand(Action execute)
            : this(execute, null)
        {
        }

        public RelayCommand(Action execute, Func<bool> canExecute)
        {
            if (execute == null)
                throw new ArgumentNullException("execute");

            _execute = execute;
            _canExecute = canExecute;
        }

        #endregion

        #region ICommand Members

        public bool CanExecute(object parameter)
        {
            return _canExecute == null ? true : _canExecute();
        }

        public event EventHandler CanExecuteChanged
        {
            add
            {
                if (_canExecute != null)
                    CommandManager.RequerySuggested += value;
            }
            remove
            {
                if (_canExecute != null)
                    CommandManager.RequerySuggested -= value;
            }
        }

        public void Execute(object parameter)
        {
            _execute();
        }

        #endregion
    }
二、使用Binding Property
     绑定属性的方法通常用于实施获取界面某个值的变化,配合Binding的Converter和ValidationRule可以很好的效果,不过在VM中要实现INotifyPropertyChanged,集合通常要实现ObservableCollection<T>。
三、使用Attatch Property
    Attatch方法通常是为了VM能够与V通过binding的方法响应一些非Command的事件,比如WindowClose,OnResized等。实现的主要思路是,自定义一个静态类,该类中定义一个AttatchProperty实现,
在XAML文档中对要施加事件的Element的Style中使用Setter进行设置(类似的方法都行,只要附加该自定义AttatchProperty属性就行)。同时在定义的类中,AttachProperty属性注册附加属性当中的属性原数据响应函数中要将DependencyObject对象的特定事件与你的响应函数进行链接。代码如下:
XAML
    <Window.Style>
        <Style TargetType="{x:Type Window}">
            <Setter 
            Property="Host:MainWindowBehavior.OnWindowCloseAction" 
            Value="{Binding }" 
            />
        </Style>
    </Window.Style>
自定义属性
        public static readonly DependencyProperty OnWindowCloseActionProperty =
            DependencyProperty.RegisterAttached(
            "OnWindowCloseAction",
            typeof(object),
            typeof(MainWindowBehavior),
            new UIPropertyMetadata(null, OnHostWindowClose));

        private static void OnHostWindowClose(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            MainWindow mainWindow = d as MainWindow;
            if (null != mainWindow)
                mainWindow.Closed += new EventHandler(mainWindow_Closed);

        }

        static void mainWindow_Closed(object sender, EventArgs e)
        {
            MainWindow mainWindow = sender as MainWindow;
            if (null != mainWindow)
            {
                MainWindowPresenter tempPresenter = mainWindow.DataContext as MainWindowPresenter;
                if (null != tempPresenter)
                    tempPresenter.Dispose();
            }
        }
写到最后:
  上面三种方法都是本人平时开发过程中经常使用的方法,基本可以满足大部分的需要。如果有进一步的需求,可以关注一下http://caliburn.codeplex.com/。类似于Message.Attach="[Event Click] = [Action Divide]"的形式就可以实现命令的链接了。

 链接:http://www.cnblogs.com/oliverxgwang/archive/2009/07/28/1532678.html

posted @ 2014-02-27 10:46  邹邹  Views(587)  Comments(0)    收藏  举报