欢迎访问移动开发之家(rcyd.net),关注移动开发教程。移动开发之家  移动开发问答|  每日更新
页面位置 : > > 内容正文

WindowsPhone开发笔记(1)—— ViewMoel

来源: 开发者 投稿于  被查看 2431 次 评论:157

WindowsPhone开发笔记(1)—— ViewMoel


废话: 前很长一段时间一直忙于写 GuoKr Reader 和 喂饭 。   现在终于可以 整理一下开发中的有点价值的东西。
 
额。。。ViewModel 这东西 直面意思就是界面对象。。他里面描述的东西应该只有 数据和业务逻辑 ,他里面不应该与任何与 界面交互相关的东西 (比如控制一个什么控件 ,动画、消息框什么的。。。。。  )发生关系(别想歪了 我故意的。。。)
 
但是我们在实际使用中VM 中的发生了一些事情 总得让VIEW 知道啊 所以MS 为我们提供了
 
System.ComponentModel.INotifyDataErrorInfo
 
System.ComponentModel.INotifyPropertyChanged
 
System.ComponentModel.InotifyPropertyChanging
 
等 通知 接口
 
我们以INotifyPropertyChanged 为例来看下结构:
 
里面有个 事件:PropertyChanged

VM 通过这些通知接口里面的事件  我们可以告知 View  发生了什么事情  至于 View 管不关心  或者关心什么那就不是 ViewModel的事情了
 
(注意: 一般来说 要绑定要界面的属性必须实现INotifyPropertyChanged 属性 也就是说在属性被修改后必须触发 PropertyChanged事件,同时Notify 接口中的事件是在UI 现场中运行的 在跨线程运行的时候一定要注意)

我们在回过头来说VM
 
一般来说或我都会实现一个 BaseViewModel 吧所需要的实现的接口和基础的方法都在里面实现好
 
using System;
using System.Net;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Threading;
using System.Windows.Navigation;
using Microsoft.Phone.Controls;
using System.Runtime.CompilerServices;
using WeiFan.Utility;

namespace WeiFan.UI.ViewModel
{
    public abstract class BaseViewModel : INotifyPropertyChanged, INotifyPropertyChanging,INotifyDataErrorInfo
    {

        Dispatcher _dispatcher;
        public BaseViewModel()
        {
           
            _dispatcher = Deployment.Current.Dispatcher;
         
        }

        protected Dispatcher Dispatcher { get { return _dispatcher; } }
        protected PhoneApplicationFrame PhoneApplicationFrame { get { return (Application.Current.RootVisual as Microsoft.Phone.Controls.PhoneApplicationFrame); } }

        private Dictionary<String, List<String>> m_errors =
           new Dictionary<string, List<string>>();
       
        public event PropertyChangedEventHandler PropertyChanged;

        public event PropertyChangingEventHandler PropertyChanging;

        public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;

        public System.Collections.IEnumerable GetErrors(string propertyName)
        {
            if (String.IsNullOrEmpty(propertyName) ||
                !m_errors.ContainsKey(propertyName)) return null;
            return m_errors[propertyName];
        }

        public bool HasErrors
        {
            get { return m_errors.Count > 0; }
        }

        protected bool SetProperty<T>(ref T storage, T value,string propertyName)
        {
            if (object.Equals(storage, value)) return false;
            this.FirePropertyChanging(new PropertyChangingEventArgs(propertyName));
            storage = value;
            this.FirePropertyChanged(new PropertyChangedEventArgs(propertyName));
            return true;
        }

        protected virtual void FirePropertyChanging(PropertyChangingEventArgs args)
        {
            if (PropertyChanging != null)
            {
                PropertyChanging(this, args);
            }
        }

        protected virtual void FirePropertyChanged(PropertyChangedEventArgs args)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, args);
            }
           
        }

        protected virtual void FireErrorsChanged(DataErrorsChangedEventArgs args)
        {
            if (ErrorsChanged != null)
                ErrorsChanged(this, args);
        }

        protected virtual void AddError(string propertyName, string error, bool isWarning)
        {
            if (!m_errors.ContainsKey(propertyName))
                m_errors[propertyName] = new List<string>();

            if (!m_errors[propertyName].Contains(error))
            {
                if (isWarning) m_errors[propertyName].Add(error);
                else m_errors[propertyName].Insert(0, error);
                FireErrorsChanged(new DataErrorsChangedEventArgs(propertyName));
            }
        }

        protected virtual void RemoveError(string propertyName, string error)
        {
            if (m_errors.ContainsKey(propertyName) &&
                m_errors[propertyName].Contains(error))
            {
                m_errors[propertyName].Remove(error);
                if (m_errors[propertyName].Count == 0) m_errors.Remove(propertyName);
                FireErrorsChanged(new DataErrorsChangedEventArgs(propertyName));
            }
        }
    }

}
 
VM 就说到这里吧。。。。下面来说怎么用他。。。。。

最简单的用法的就是在页面代码中 (xaml.cs) 构造出来比如 BaseViewModel baseVM = new BaseViewModel();

然后使用  (里面公开的属性 方法 什么的 爱怎么搞怎么搞。。。。。)

如果要在xaml 中binding 的话就要把设置控件(或控件所属的容器)的DataContext设置为该VM (别的方式我还不知道。。。。。。 )


比如:

在xmal.cs 中

LayoutRoot.DataContent = new XXXXViewMode();


或者:

<Grid.DataContext>

          <WeiFan_UI_ViewModel:StatusVM/>

         </Grid.DataContext>

如果是后者的话 VM 会在空间Load的时候构造 但是 VM 必须有一个无参数的购找函数。。。


那么

如果VM 由于业务原因  我们总需要在构造的时候需要一些参数进行初始化那么肿么办呢。。。。。。。。。。。

我表示我还没找到好的解决方案。。。。。


我想到的方法有个两个

1、就在xaml.cs  中写吧

但是 我们在xaml 中banding的时候会变得很纠结。。。。

具体怎么纠结 各位自己去体会吧。。。。

2、还是xaml 做vm吧。。。  不过我们得写个初始方法

额。。。 比如。。。
 
 
public class StatusVM:BaseViewModel 
{

    bool m_isInitialed = false;

        public bool IsInitialed
        {
            get { return m_isInitialed; }

            set { SetProperty(ref m_isInitialed, value, "IsInitialed"); }
        }

       public void Initialization(string statusID)
       { …....           }
}
 

xaml 中的写法不变 

在xaml.cs 的只是需要使用vm 前 构造前 调用Initialization 进行初始化。。。。。
 
 
 
摘自 F-sea

相关文章

    暂无相关文章
相关频道:

用户评论