<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      談談 INotifyPropertyChanged 的實現

      INotifyPropertyChanged 接口是 WPF/Silverlight 開發中非常重要的接口, 它構成了 ViewModel 的基礎, 數據綁定基本上都需要這個接口。 所以, 對它的實現也顯得非常重要, 下面接貼出我知道的幾種實現方式, 希望能起到拋磚引玉的作用。

      一般的實現方式

      這是一種再普通不過的實現方式, 代碼如下:

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

      這種方式稱之為一般的實現方式, 因為它確實是太普通不過了, 而且使用起來也讓人感到厭惡, 因為必須指定手工指定屬性名稱:

      public class MyViewModel : NotifyPropertyChanged {
      
         private int _myField;
      
         public int MyProperty {
            get { return _myField; }
            set {
               _myField = value;
               OnPropertyChanged("MyProperty");
            }
         }
      }

      lambda 表達式實現方式

      對 lambda 表達式比較熟悉的同學可以考慮用 lambda 表達式實現屬性名稱傳遞, 在 NotifyPropertyChanged 類添加一個這樣的方法:

      protected void SetProperty<T>(ref T propField, T value, Expression<Func<T>> expr) {
         var bodyExpr = expr.Body as System.Linq.Expressions.MemberExpression;
         if (bodyExpr == null) {
            throw new ArgumentException("Expression must be a MemberExpression!", "expr");
         }
         var propInfo = bodyExpr.Member as PropertyInfo;
         if (propInfo == null) {
            throw new ArgumentException("Expression must be a PropertyExpression!", "expr");
         }
         var propName = propInfo.Name;
         propField = value;
         this.OnPropertyChanged(propName);
      }

      有了這個方法, NotifyPropertyChanged 基類使用起來就令人舒服了很多:

      public class MyViewModel : NotifyPropertyChanged {
      
         private int _myField;
      
         public int MyProperty {
            get { return _myField; }
            set {
               base.SetProperty(ref _myField, value, () => this.MyProperty);
                }
         }
      }

      這樣一來, 把屬性名稱用字符串傳遞改成了用 lambda 表達式傳遞, 減少了硬編碼, 確實方便了不少, 但是還是感覺略微麻煩了一些, 還是要寫一個 lambda 表達式來傳遞屬性名稱。

      攔截方式實現

      如果對 Castal.DynamicProxy 有印象的話, 可以考慮使用 DynamicProxy 進行攔截實現, 我的實現如下:

      // 1. 先定義一個攔截器, 重寫 PostProcess 方法, 當發現是調用以 set_ 開頭的方法時,
      //    一般就是設置屬性了, 可以在這里觸發相應的事件。
      internal class NotifyPropertyChangedInterceptor : StandardInterceptor {
      
         protected override void PostProceed(IInvocation invocation) {
            base.PostProceed(invocation);
            var methodName = invocation.Method.Name;
            if (methodName.StartsWith("set_")) {
               var propertyName = methodName.Substring(4);
               var target = invocation.Proxy as NotifyPropertyChanged;
               if (target != null) {
                  target.OnPropertyChanged(propertyName);
               }
            }
         }
      }
      
      // 2. 再定義一個幫助類, 提供一個工廠方法創建代理類。
      public static class ViewModelHelper {
      
         private static readonly ProxyGenerator ProxyGenerator = new ProxyGenerator();
         private static readonly NotifyPropertyChangedInterceptor Interceptor
               = new NotifyPropertyChangedInterceptor();
      
         public static T CreateProxy<T>(T obj) where T : class, INotifyPropertyChanged {
            return ProxyGenerator.CreateClassProxyWithTarget(obj, Interceptor);
         }
      }

      使用起來也是很方便的, 只是創建 ViewModel 對象時必須用幫助類來創建實例, 代碼如下:

      public class MyViewModel : NotifyPropertyChanged {
      
         // 定義屬性時不需要任何基類方法, 和普通屬性沒有什么兩樣。
         public int MyProperty {
            get; set;
         }
      }
      // 使用時需要這樣創建實例:
      var viewModel = ViewModelHelper.CreateProxy<MyViewModel>();
      viewModel.MyProperty = 100;

      不過這種實現的缺點就是所有的屬性都會觸發 PropertyChanged 事件, 而且只能觸發一個事件, 而在實際開發中, 偶爾需要設置一個屬性, 觸發多個 PropertyChanged 事件。

      未來 .Net 4.5 的實現方式

      在即將發布的 .Net 4.5 中, 提供了 CallerMemberNameAttribute 標記, 利用這個屬性, 可以將上面提供的 SetProperty 方法進行改造, 這樣的實現才是最完美的:

      protected void SetProperty<T>(ref T storage, T value, [CallerMemberName] String propertyName = null) {
         if (object.Equals(storage, value)) return;
      
         storage = value;
         this.OnPropertyChanged(propertyName);
      }

      由于有了 CallerMemberName 標記助陣, 可以說使用起來是非常方便了:

      public class MyViewModel : NotifyPropertyChanged {
      
         private int _myField;
      
         public int MyProperty {
            get { return _myField; }
            set {
               base.SetProperty(ref _myField, value);
            }
         }
      }

      這種方法雖然好,不過卻只有在 .Net 4.5 中才有, 而且也許永遠不會添加到 Silverlight 中。

      posted @ 2012-08-13 15:08  張志敏  閱讀(19826)  評論(12)    收藏  舉報
      主站蜘蛛池模板: 精品无码国产日韩制服丝袜| 午夜福利在线观看6080| 2021国产成人精品久久 | 国产系列高清精品第一页| 婷婷丁香五月深爱憿情网| 久久免费观看午夜成人网站| 日韩乱码卡一卡2卡三卡四| 九九热精品在线观看| 粉嫩一区二区三区国产精品| 日本三级理论久久人妻电影| 国产成人a在线观看视频免费| 免费看的日韩精品黄色片| 中文字幕无码不卡在线| 亚洲欧美人成电影在线观看| 亚洲国产精品久久久天堂麻豆宅男 | 亚洲国产精品久久一线不卡| 亚洲国产在一区二区三区| 成人亚洲av免费在线| 国产成人精品区一区二区| 国产精品亚洲А∨天堂免| 亚洲深夜精品在线观看| 免费a级黄毛片| 综合色天天久久| 狠狠色婷婷久久综合频道日韩| 亚洲伊人久久大香线蕉| 日韩在线成年视频人网站观看| 日韩高清不卡一区二区三区| 在线观看潮喷失禁大喷水无码| 久久综合国产色美利坚| 艳妇乳肉豪妇荡乳xxx| 成人综合人人爽一区二区| 祁阳县| 国产精品一区二区中文| 亚洲欧美电影在线一区二区| A级毛片无码久久精品免费| 免费无码又爽又刺激网站直播| 国产欧美精品一区二区三区| 色综合久久夜色精品国产| 精品免费看国产一区二区| 免费无码成人AV片在线| 成在人线av无码免费看网站直播 |