Silverlight MVVM 贴近实战(七)

Silverlight MVVM 贴近实战(七),第1张

概述这个行业里,山外有山,人外有人,忽然觉得自己是个菜鸟。 今天我们通过用户管理模块来系统的讲述关于Action,Trigger的使用。首先还是先上一张图,调一下胃口。 这个图中的Grid怎会变成如此摸样,是的,在这里我们用到了一点点3D的效果。首先我们先从前台代码入手。 <controls:ChildWindow x:Class="MISInfoManage.UserManage

这个行业里,山外有山,人外有人,忽然觉得自己是个菜鸟。

今天我们通过用户管理模块来系统的讲述关于Action,Trigger的使用。首先还是先上一张图,调一下胃口。

这个图中的GrID怎会变成如此摸样,是的,在这里我们用到了一点点3D的效果。首先我们先从前台代码入手。

  <controls:ChilDWindow x:Class="MISInfoManage.UserManageVIEw"                /*此处省略部分代码*/              xmlns:resource="clr-namespace:MISInfoManage.Resources"                     xmlns:trigger="clr-namespace:MISInfoManage.Trigger"                xmlns:i="clr-namespace:System.windows.Interactivity;assembly=System.windows.Interactivity">       /*此处省略部分代码*/            <GrID x:name="LayoutRoot" margin="2">             <GrID.RowDeFinitions>                 <RowDeFinition Height="65"/>                 <RowDeFinition Height="297"/>                 <RowDeFinition Height="auto"/>             </GrID.RowDeFinitions>             <sdk:DataGrID GrID.Row="0" GrID.Column="0" Height="300" WIDth="540"                                /*此处省略部分代码*/   >                          <sdk:DataGrID.Projection>                     <PlaneProjection RotationX="0" RotationY="10" RotationZ="0"></PlaneProjection>                 </sdk:DataGrID.Projection>                 <sdk:DataGrID.Effect>                     <DropShadowEffect BlurRadius="5" color="Black" ShadowDepth="8" Opacity="0.8"/>                 </sdk:DataGrID.Effect>                 <i:Interaction.Triggers>                     <i:EventTrigger Eventname="SelectionChanged">                         <trigger:SelectChangeTargetTrigger Targetname="txtUserNo">                         </trigger:SelectChangeTargetTrigger>                         <trigger:SelectChangeTargetTrigger Targetname="cmbType">                         </trigger:SelectChangeTargetTrigger>                         <trigger:SelectChangeTargetTrigger Targetname="cmbState">                         </trigger:SelectChangeTargetTrigger>                     </i:EventTrigger>                 </i:Interaction.Triggers>                 <sdk:DataGrID.Columns>              /*此处省略部分代码*/               </sdk:DataGrID.Columns>                  </sdk:DataGrID>             <sdk:DataPager x:name="dataPager"                            GrID.Row="1" borderThickness="1"                            borderBrush="Black"                            displayMode="FirstLastPrevIoUsNextNumeric"                            PageSize="10">             </sdk:DataPager>             <border borderThickness="1" margin="0,5,5" Background="Silver" borderBrush="Black" GrID.Row="2" GrID.Column="0">                 /*此处省略部分代码*/                           <Image Source="Images/windows.png" Opacity="0.7" GrID.Row="0" GrID.Column="0"/>                                          <TextBox x:name="txtUserNo" Foreground="Silver" borderThickness="0" GrID.Row="0" GrID.Column="1" Text="{Binding UserNo,Mode=OneWay}">                                 <i:Interaction.Triggers>                                    <i:EventTrigger Eventname="GotFocus">                                        <trigger:FocusTrigger></trigger:FocusTrigger>                                    </i:EventTrigger>                                     <i:EventTrigger Eventname="LostFocus">                                         <trigger:LostFocusTrigger>                                         </trigger:LostFocusTrigger>                                     </i:EventTrigger>                                 </i:Interaction.Triggers>                             </TextBox>                         </GrID>                     </border>                    /*此处省略部分代码*/                   <ComboBox x:name="cmbType" GrID.Row="1" GrID.Column="1"                                            Background="AliceBlue"                                 HorizontalAlignment="left" margin="2,0" WIDth="200"                               ItemsSource="{Binding UserTypeList,Mode=OneWay}"                                 SelectedItem="{Binding UserType}">                         <ComboBox.ItemTemplate>                             <DataTemplate>                                 <StackPanel OrIEntation="Horizontal">                                     <Image Source="{Binding UserTypeImage}" Height="22" Stretch="UniformToFill"></Image>                                     <TextBlock Text="{Binding UserTypename,Mode=TwoWay}" FontWeight="Bold" margin="2,0"/>                                 </StackPanel>                             </DataTemplate>                         </ComboBox.ItemTemplate>                     </ComboBox>                    /*此处省略部分代码*/               </GrID>                  </border>         </GrID>     </controls:ChilDWindow>   

在这里布局我们就不说了,相信看过前几篇的都明白。首先我们看有这么一段代码

  <sdk:DataGrID.Projection>                     <PlaneProjection RotationX="0" RotationY="10" RotationZ="0"></PlaneProjection>                 </sdk:DataGrID.Projection>   

这段代码是设置DataGrID的3D效果的,在这里我们设置其x轴的旋转角为0,Y轴旋转角为10,Z轴是0。怎么理解呢?这就好比空间一个三维坐标,X轴转动你想象成手指头抓住X轴的正方向,用手指去撵的让它转动。同理,Y轴和Z轴也是同样的道理。我们在这里设置正角,是让它逆时针转动,如果是负角则是顺时针。OK,我们接着看下面这样一段代码

  <i:Interaction.Triggers>                     <i:EventTrigger Eventname="SelectionChanged">                         <trigger:SelectChangeTargetTrigger Targetname="txtUserNo">                         </trigger:SelectChangeTargetTrigger>                         <trigger:SelectChangeTargetTrigger Targetname="cmbType">                         </trigger:SelectChangeTargetTrigger>                         <trigger:SelectChangeTargetTrigger Targetname="cmbState">                         </trigger:SelectChangeTargetTrigger>                     </i:EventTrigger>                 </i:Interaction.Triggers>   

这段涉及到我开始提到的Action,在这里我们使用到了TargetedTriggerAction,也就是在DataGrID SelectionChanged事件触发的时候,会对这三个Targetname指定的UIElement进行UI的变化。我们看看这个SelectChangeTargetTrigger 。

  namespace MISInfoManage.Trigger      {          public class SelectChangeTargetTrigger : TargetedTriggerAction<DependencyObject>          {              private DependencyObject element;              public SelectChangeTargetTrigger()              { }                   protected overrIDe voID OnAttached()              {                  base.OnAttached();                  if (Target != null)                  {                      element = Target;                  }              }                   protected overrIDe voID OnDetaching()              {                  base.OnDetaching();                  element = null;              }                   protected overrIDe voID OnTargetChanged(DependencyObject oldTarget, DependencyObject newTarget)              {                  base.OnTargetChanged(oldTarget, newTarget);                  if (element == null)                  {                      element = newTarget;                  }              }                   protected overrIDe voID Invoke(object parameter)              {                  if ((this.Associatedobject as DataGrID).SelectedItem != null)                  {                      if (this.Target.GetType() == typeof(TextBox))                      {                          TextBox textBox = (Target as TextBox);                          textBox.IsReadonly = true;                          if (textBox.name == "txtUserNo")                          {                              textBox.Foreground = new SolIDcolorBrush(colors.Black);                          }                      }                      if (this.GetType() == typeof(ComboBox))                      {                          (Target as ComboBox).IsEnabled = false;                      }                   }              }          }        

在这里需要注意的是要引用System.windows.Interactivity命名空间。结合界面代码我们可以看出,当DataGrID的SelectionChanged事件触发以后,会调用Invoke方法,也就是遍历该TargetedTrigger下的目标元素,在这里是对文本框设置Readonly,对ComboBox设置IsEnabled。这样就有效的实现了UI与逻辑的分离,这个将放在viewmodel中做处理。再往下走我们发现这样一段代码

  <border borderThickness="1" borderBrush="Black" GrID.Row="0" GrID.Column="1"  WIDth="200">                         <GrID>                             <GrID.RowDeFinitions>                                 <RowDeFinition Height="auto"></RowDeFinition>                             </GrID.RowDeFinitions>                             <GrID.ColumnDeFinitions>                                 <ColumnDeFinition WIDth="auto"></ColumnDeFinition>                                 <ColumnDeFinition WIDth="*"></ColumnDeFinition>                             </GrID.ColumnDeFinitions>                             <Image Source="Images/windows.png" Opacity="0.7" GrID.Row="0" GrID.Column="0"/>                             <TextBox x:name="txtUserNo" Foreground="Silver" borderThickness="0" GrID.Row="0" GrID.Column="1" Text="{Binding UserNo,Mode=OneWay}">                                 <i:Interaction.Triggers>                                    <i:EventTrigger Eventname="GotFocus">                                        <trigger:FocusTrigger></trigger:FocusTrigger>                                    </i:EventTrigger>                                     <i:EventTrigger Eventname="LostFocus">                                         <trigger:LostFocusTrigger>                                         </trigger:LostFocusTrigger>                                     </i:EventTrigger>                                 </i:Interaction.Triggers>                             </TextBox>                         </GrID>                     </border>   

这段代码是模拟了一个水印文本框效果,在这里使用到了Trigger,一个是FocusTrigger,一个是LostFocusTrigger,结合起来实现水印效果。我们看看这两个Trigger的代码

  public class FocusTrigger:TriggerAction<TextBox>          {              protected overrIDe voID OnAttached()              {                  base.OnAttached();              }                   protected overrIDe voID OnDetaching()              {                  base.OnDetaching();              }                   protected overrIDe voID Invoke(object parameter)              {                  if (this.Associatedobject.Text.Trim() == "请输入用户名")                  {                      this.Associatedobject.Text = string.Empty;                      this.Associatedobject.Foreground = new SolIDcolorBrush(colors.Black);                  }              }          }   

这个是FocusTrigger,文本框获取焦点时,调用Invoke方法。这个时候当文本框的值是“请输入用户名”的时候,就清掉文本框,并且字体前景色设置为黑色。我们再看看LostFocusTrigger的代码

  public class LostFocusTrigger : TriggerAction<TextBox>          {              protected overrIDe voID OnAttached()              {                  base.OnAttached();              }                   protected overrIDe voID OnDetaching()              {                  base.OnDetaching();              }                   protected overrIDe voID Invoke(object parameter)              {                  if (string.IsNullOrWhiteSpace(this.Associatedobject.Text))                  {                      this.Associatedobject.Foreground = new SolIDcolorBrush(colors.Gray);                      this.Associatedobject.Text = "请输入用户名";                  }              }          }   

当文本框失去焦点的时候,如果文本框值为空或者空白,那么文本框的值为“请输入用户名”,前景色改为Gray。OK,我们继续往下看

  <ComboBox x:name="cmbType" GrID.Row="1" GrID.Column="1"                               Background="AliceBlue"                                 HorizontalAlignment="left" margin="2,0"/>                                 </StackPanel>                             </DataTemplate>                         </ComboBox.ItemTemplate>                     </ComboBox>   

在这里我们使用了ComboBox的项模板,在这里你可以自定义你想要的模版。在这里我放了一个图片和一个文本。如下图所示

怎么样,很不错吧。最后在这列我们重点看看分页。我这可是服务端分页。

  <sdk:DataPager x:name="dataPager"                            GrID.Row="1" borderThickness="1"                            borderBrush="Black"                            displayMode="FirstLastPrevIoUsNextNumeric"                            PageSize="10">             </sdk:DataPager>   

这个时候我就要把viewmodel的代码贴出来了,否则没法讲述清楚。

  namespace MISInfoManage.viewmodels      {          public class UserManageviewmodel : INotifyPropertyChanged          {              private bool isFirstLoad;              public UserManageVIEw userManageVIEw;              DataPagerTrigger dataPagertrigger;              List<int> List = new List<int>();              public UserManageviewmodel()              {                  this.InitData(1, 10);              }                   public UserManageviewmodel(UserManageVIEw userManageVIEw)                  : this()              {                  isFirstLoad = true;                  this.userManageVIEw = userManageVIEw;                  this.dataPagertrigger = new DataPagerTrigger(this);                  this.AttachTrigger();                  this.SetTitle();                  this.UserNo = "请输入用户名";              }                   #region property                  /*此处省略部分代码*/           #endregion                                #region method                   private voID AttachTrigger()              {                  this.dataPagertrigger.Attach(this.userManageVIEw.dataPager);              }                   private voID SetTitle()              {                  Image image = new Image();                  image.source = new BitmAPImage(new Uri("../Images/drag.png", UriKind.relative));                  image.Height = 30;                  image.WIDth = 20;                  TextBlock textBlock = new TextBlock();                  textBlock.margin = new Thickness(5, 0, 0);                  textBlock.Text = "用户管理";                  textBlock.FontSize = 14;                  textBlock.FontWeight = FontWeights.Bold;                  StackPanel stackPanel = new StackPanel();                  stackPanel.OrIEntation = OrIEntation.Horizontal;                  stackPanel.Background = new RadialGradIEntBrush(colors.Gray, colors.brown);                  stackPanel.WIDth = this.userManageVIEw.WIDth;                  stackPanel.Children.Add(image);                  stackPanel.Children.Add(textBlock);                  this.userManageVIEw.Title = stackPanel;              }                   private voID GetUserList(UserRequest request, EventHandler<GetUserListCompletedEventArgs> callback)              {                  UserManageService.UserManageServiceClIEnt clIEnt = new UserManageServiceClIEnt();                  clIEnt.GetUserListCompleted += callback;                  clIEnt.GetUserListAsync(request);              }                  /*此处省略部分代码*/                             private voID GetUserPagedCollection(int totalCount)              {                  List.Clear();                  for (int i = 0; i < totalCount; i++)                  {                      List.Add(i);                  }                  PagedCollectionVIEw pagedCollectionVIEw = new PagedCollectionVIEw(List);                  this.userManageVIEw.dataPager.source = pagedCollectionVIEw;                  isFirstLoad = false;              }                   public voID GetDataByPage(int pageIndex, int pageSize)              {                  UserRequest userRequest = new UserRequest()                  {                      PageIndex = pageIndex,                     PageSize = pageSize                  };                  this.GetUserList(userRequest, (obj, args) =>                  {                      if (args.Error == null)                      {                          this.UserResponse = args.Result;                          this.UserList = userResponse.UserList;                          if (isFirstLoad)                          {                              this.GetUserPagedCollection(this.UserResponse.RecordCount);                          }                      }                  });              }                   private voID InitData(int pageIndex, int pageSize)              {                  this.GetDataByPage(pageIndex,pageSize);                  this.GetUserStateList();                  this.GetUserTypeList();              }                   #endregion                   /*此处省略部分代码*/       }                     

在viewmodel的代码中,我们发现了这样一段代码

  this.dataPagertrigger = new DataPagerTrigger(this);                 this.AttachTrigger();   
  private voID AttachTrigger()             {                 this.dataPagertrigger.Attach(this.userManageVIEw.dataPager);             }   

这段代码就是在初始化viewmodel的时候,将dataPager控件附加给dataPagertrigger。我们看看dataPagertrigger代码

  public class DataPagerTrigger : TriggerBase<UIElement>          {              public UserManageviewmodel userManageviewmodel;              public DataPagerTrigger(UserManageviewmodel userManageviewmodel)              {                  this.userManageviewmodel = userManageviewmodel;              }                   protected overrIDe voID OnAttached()              {                  base.OnAttached();                  if (this.Associatedobject is DataPager)                  {                      (this.Associatedobject as DataPager).PageIndexChanged += this.PageIndexChanged;                  }              }                   protected overrIDe voID OnDetaching()              {                  base.OnDetaching();                  if (this.Associatedobject is DataPager)                  {                      (this.Associatedobject as DataPager).PageIndexChanged -= this.PageIndexChanged;                  }              }                   private voID PageIndexChanged(object sender, EventArgs e)              {                  DataPager dataPager = sender as DataPager;                  this.userManageviewmodel.GetDataByPage(dataPager.PageIndex, dataPager.PageSize);              }          }   

这个类继承自TriggerBase,我们给其注册了一个PageIndexChanged 事件,当DataPager控件页码变化时,调用PageIndexChanged方法,在这个方法里调用userManageviewmodel的GetDataByPage方法。在GetDataByPage方法中先获取用户列表,判断如果是第一次加载,就给 DataPager控件附一个PagedCollectionVIEw类型的一个source,在这里通过模拟,可以有效的进行分页,因为目前我发现这个分页控件只能客户端分页。所以模拟一个List<int>,它的总条数==表的总记录。这样就实现了服务端分页,如果谁想要源码,可以加入群205217091。我们看看分页的效果

最后大家可能注意到d出界面的Title和以前的不一样,这里你可以自定义,如viewmodel中的SetTitle方法。好了,时间不早了,洗洗睡!

总结

以上是内存溢出为你收集整理的Silverlight MVVM 贴近实战(七)全部内容,希望文章能够帮你解决Silverlight MVVM 贴近实战(七)所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1065680.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-26
下一篇 2022-05-26

发表评论

登录后才能评论

评论列表(0条)

保存