• WP学习笔记(4)MVVM入门 第一部分 INotifyPropertyChanged和ICommand


    这一篇到MVVM了,心里很是忐忑,听说MVVM很长时间了但是一直也没有真正用过,两年前做Silverlight那会项目里也没怎么用,而且那时候还没有windows phone和win8,所以也没太在意,悔不当初啊。这一篇我就多用代码实例说话,少用描述性的文字,以免误人子弟。

    打开前几篇的代码,上一篇我们把json转换成了实体类中的数据并且用弹出框显示了一下,那么怎么显示到界面上呢,也许会这么做

    1 HttpClient hc = new HttpClient();
    2 var task = await hc.GetAsync("http://www.weather.com.cn/data/cityinfo/101010100.html");
    3 string result = await task.Content.ReadAsStringAsync();
    4 JObject obj = JObject.Parse(result);
    5  WeatherModel1 details = (WeatherModel1)JsonConvert.DeserializeObject(obj["weatherinfo"].ToString(), typeof(WeatherModel1));
    6 this.DataContext = details;  

    在页面里面这样

    1 <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
    2    <Button Content="Button" HorizontalAlignment="Left" Margin="137,103,0,0" VerticalAlignment="Top"  Click="Button_Click"/>
    3    <TextBlock HorizontalAlignment="Left" Margin="119,265,0,0" TextWrapping="Wrap" Text="{Binding city}" VerticalAlignment="Top"/>
    4 
    5 </Grid>

     可以显示没问题,但是太丑陋了,要在code-behid里写很多代码,搞的显示和逻辑混乱不堪,刷新一次请求就要重新绑定一次页面的DataContext,而且这个DataContext要是新的引用(也就是说要重新new一个model出来)显示上才会刷新。下面我们引入ViewModel
    新建一个类叫WeatherViewModel

     1 public class WeatherViewModel : INotifyPropertyChanged
     2     {
     3         //public WeatherViewModel()
     4         //{
     5         //    if (updateCmd == null)
     6         //    {
     7         //        updateCmd = new UpdateCmd(this);
     8         //    }
     9         //}
    10         public event PropertyChangedEventHandler PropertyChanged;
    11         //public ICommand updateCmd { get; private set; }
    12         private string _city;
    13         public string city
    14         {
    15             get
    16             {
    17                 return _city;
    18             }
    19             set
    20             {
    21                 _city = value;
    22                 if (PropertyChanged != null)
    23                 {
    24                     PropertyChanged(this, new PropertyChangedEventArgs("city"));
    25                 }
    26             }
    27         }
    28     }

    里面有几行注释掉的代码,不用管它那是一会要用的。这个类实现了INotifyPropertyChanged接口,它的作用就是通知UI属性变更了,UI知道后就会重新调用属性的get获取。
    下面几个地方我们这么改,打开app.xaml,找到添加资源的<Application.Resources>标签,对,就是添加动画那里。然后在里面添加下面代码

    <my:WeatherViewModel xmlns:my="clr-namespace:PhoneApp3" x:Key="weather"/>

    在页面的头部添加DataContext="{StaticResource weather}"
    把最开始写在code-behind里的this.DataContext = details改成((WeatherViewModel)this.DataContext).city = details.city;

    一样可以显示,而且我们只是给属性重新赋值了。不过codebehind里的代码还是太多,层次还是不清晰,需要继续改造。不在code-behind里响应点击事件,改用command

    新建一个类就叫UpdateCmd

     1 public class UpdateCmd : ICommand
     2     {
     3         private WeatherViewModel _weather;
     4         public UpdateCmd(WeatherViewModel weather)
     5         {
     6             _weather = weather;
     7         }
     8         public bool CanExecute(object parameter)
     9         {
    10             if (parameter != null)
    11             {
    12                 CanExecuteChanged(parameter, new EventArgs());
    13             }
    14             return true;
    15 
    16             //throw new NotImplementedException();
    17         }
    18 
    19         public event EventHandler CanExecuteChanged;
    20 
    21         public async void Execute(object parameter)
    22         {
    23             //System.Windows.MessageBox.Show("a");
    24             //throw new NotImplementedException();
    25             HttpClient hc = new HttpClient();
    26             var task = await hc.GetAsync("http://www.weather.com.cn/data/cityinfo/101010100.html");
    27             string result = await task.Content.ReadAsStringAsync();
    28             JObject obj = JObject.Parse(result);
    29             WeatherModel1 details = (WeatherModel1)JsonConvert.DeserializeObject(obj["weatherinfo"].ToString(), typeof(WeatherModel1));
    30             _weather.city = details.city;
    31         }
    32     }

    把WeatherViewModel里注释的代码打开。把xaml中button的click换成command

    1 <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
    2    <Button Content="Button" HorizontalAlignment="Left" Margin="137,103,0,0" VerticalAlignment="Top" Command="{Binding updateCmd}"/>
    3    <TextBlock HorizontalAlignment="Left" Margin="119,265,0,0" TextWrapping="Wrap" Text="{Binding city}" VerticalAlignment="Top"/>
    4 </Grid>

    现在我们可以把code-behind里所有不是自带的,前几篇添加的代码全部注释掉了。测试一下看看,我们没有在code-behind里写一句代码就实现了数据的显示。而且我们也完成了view-view model-model分层。上面的代码里,Command中Excute部分也应该提取出来成为service。
    关于INotifyPropertyChanged和ICommand更多的信息感兴趣的还是baidu吧,我就不这里献丑了,网上还是很多的。今天这篇就到这,下一篇简单应用一下DependencyProperty。

  • 相关阅读:
    IO
    mouseover,mouseout和mouseenter,mouseleave
    【译】addEventListener 第二个参数
    Git 常用命令
    我对Backbone中url属性的理解
    小失误引起大失败
    收集各大网站的登录页面
    随笔2
    随笔1
    创建数据库
  • 原文地址:https://www.cnblogs.com/titans110/p/3182332.html
Copyright © 2020-2023  润新知