这个行业里,山外有山,人外有人,忽然觉得自己是个菜鸟。
今天我们通过用户管理模块来系统的讲述关于Action,Trigger的使用。首先还是先上一张图,调一下胃口。
这个图中的Grid怎会变成如此摸样,是的,在这里我们用到了一点点3D的效果。首先我们先从前台代码入手。
- <controls:ChildWindow x:Class="MISInfoManage.UserManageView"
@H_404_32@ /*此处省略部分代码*/ xmlns:resource="clr-namespace:MISInfoManage.Resources" @H_404_32@ @H_404_32@ xmlns:trigger="clr-namespace:MISInfoManage.Trigger"- xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity">
@H_404_32@ /*此处省略部分代码*/ @H_404_32@ <Grid x:Name="LayoutRoot" Margin="2"> @H_404_32@ <Grid.RowDeFinitions>- <RowDeFinition Height="65"/>
@H_404_32@ <RowDeFinition Height="297"/>- <RowDeFinition Height="Auto"/>
@H_404_32@ </Grid.RowDeFinitions>- <sdk:DataGrid Grid.Row="0" Grid.Column="0" Height="300" Width="540"
@H_404_32@ /*此处省略部分代码*/ > @H_404_32@- <sdk:DataGrid.Projection>
@H_404_32@ <PlaneProjection RotationX="0" RotationY="10" RotationZ="0"></PlaneProjection>- </sdk:DataGrid.Projection>
@H_404_32@ <sdk:DataGrid.Effect>- <DropShadowEffect BlurRadius="5" Color="Black" ShadowDepth="8" Opacity="0.8"/>
@H_404_32@ </sdk:DataGrid.Effect>- <i:Interaction.Triggers>
@H_404_32@ <i:EventTrigger EventName="SelectionChanged">- <trigger:SelectChangeTargetTrigger TargetName="txtUserNo">
@H_404_32@ </trigger:SelectChangeTargetTrigger>- <trigger:SelectChangeTargetTrigger TargetName="cmbType">
@H_404_32@ </trigger:SelectChangeTargetTrigger>- <trigger:SelectChangeTargetTrigger TargetName="cmbState">
@H_404_32@ </trigger:SelectChangeTargetTrigger>- </i:EventTrigger>
@H_404_32@ </i:Interaction.Triggers>- <sdk:DataGrid.Columns>
@H_404_32@ /*此处省略部分代码*/ </sdk:DataGrid.Columns> @H_404_32@ @H_404_32@ </sdk:DataGrid>- <sdk:DataPager x:Name="dataPager"
@H_404_32@ Grid.Row="1" BorderThickness="1"- BorderBrush="Black"
@H_404_32@ displayMode="FirstLastPrevIoUsNextNumeric"- PageSize="10">
@H_404_32@ </sdk:DataPager>- <Border BorderThickness="1" Margin="0,5,5" Background="Silver" BorderBrush="Black" Grid.Row="2" Grid.Column="0">
@H_404_32@ /*此处省略部分代码*/ <Image Source="Images/Windows.png" Opacity="0.7" Grid.Row="0" Grid.Column="0"/> @H_404_32@ @H_404_32@- <TextBox x:Name="txtUserNo" Foreground="Silver" BorderThickness="0" Grid.Row="0" Grid.Column="1" Text="{Binding UserNo,Mode=OneWay}">
@H_404_32@ <i:Interaction.Triggers>- <i:EventTrigger EventName="GotFocus">
@H_404_32@ <trigger:FocusTrigger></trigger:FocusTrigger>- </i:EventTrigger>
@H_404_32@ <i:EventTrigger EventName="LostFocus">- <trigger:LostFocusTrigger>
@H_404_32@ </trigger:LostFocusTrigger>- </i:EventTrigger>
@H_404_32@ </i:Interaction.Triggers>- </TextBox>
@H_404_32@ </Grid>- </Border>
@H_404_32@ /*此处省略部分代码*/ <ComboBox x:Name="cmbType" Grid.Row="1" Grid.Column="1" @H_404_32@ @H_404_32@ @H_404_32@ Background="AliceBlue"- HorizontalAlignment="Left" Margin="2,0" Width="200"
@H_404_32@ ItemsSource="{Binding UserTypeList,Mode=OneWay}"- SelectedItem="{Binding UserType}">
@H_404_32@ <ComboBox.ItemTemplate>- <DataTemplate>
@H_404_32@ <StackPanel Orientation="Horizontal">- <Image Source="{Binding UserTypeImage}" Height="22" Stretch="UniformToFill"></Image>
@H_404_32@ <TextBlock Text="{Binding UserTypeName,Mode=TwoWay}" FontWeight="Bold" Margin="2,0"/>- </StackPanel>
@H_404_32@ </DataTemplate>- </ComboBox.ItemTemplate>
@H_404_32@ </ComboBox>- /*此处省略部分代码*/ </Grid>
- @H_404_32@ </Border>
- </Grid>
@H_404_32@ </controls:ChildWindow>
在这里布局我们就不说了,相信看过前几篇的都明白。首先我们看有这么一段代码
- <sdk:DataGrid.Projection>
@H_404_32@ <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>
@H_404_32@ <i:EventTrigger EventName="SelectionChanged">- <trigger:SelectChangeTargetTrigger TargetName="txtUserNo">
@H_404_32@ </trigger:SelectChangeTargetTrigger>- <trigger:SelectChangeTargetTrigger TargetName="cmbType">
@H_404_32@ </trigger:SelectChangeTargetTrigger>- <trigger:SelectChangeTargetTrigger TargetName="cmbState">
@H_404_32@ </trigger:SelectChangeTargetTrigger>- </i:EventTrigger>
@H_404_32@ </i:Interaction.Triggers>
这段涉及到我开始提到的Action,在这里我们使用到了TargetedTriggerAction,也就是在DataGrid SelectionChanged事件触发的时候,会对这三个TargetName指定的UIElement进行UI的变化。我们看看这个SelectChangeTargetTrigger 。
- namespace MISInfoManage.Trigger
@H_404_32@{- public class SelectChangeTargetTrigger : TargetedTriggerAction<DependencyObject>
@H_404_32@ {- private DependencyObject element;
@H_404_32@ public SelectChangeTargetTrigger()- { }
@H_404_32@- protected override void OnAttached()
@H_404_32@ {- base.OnAttached();
@H_404_32@ if (Target != null)- {
@H_404_32@ element = Target;- }
@H_404_32@ }- @H_404_32@ protected override void OnDetaching()
- {
@H_404_32@ base.OnDetaching();- element = null;
@H_404_32@ }- @H_404_32@ protected override void OnTargetChanged(DependencyObject oldTarget, DependencyObject newTarget)
- {
@H_404_32@ base.OnTargetChanged(oldTarget, newTarget);- if (element == null)
@H_404_32@ {- element = newTarget;
@H_404_32@ }- }
@H_404_32@- protected override void Invoke(object parameter)
@H_404_32@ {- if ((this.Associatedobject as DataGrid).SelectedItem != null)
@H_404_32@ {- if (this.Target.GetType() == typeof(TextBox))
@H_404_32@ {- TextBox textBox = (Target as TextBox);
@H_404_32@ textBox.IsReadOnly = true;- if (textBox.Name == "txtUserNo")
@H_404_32@ {- textBox.Foreground = new SolidColorBrush(Colors.Black);
@H_404_32@ }- }
@H_404_32@ if (this.GetType() == typeof(ComboBox))- {
@H_404_32@ (Target as ComboBox).IsEnabled = false;- }
@H_404_32@ }- }
@H_404_32@ }- }
在这里需要注意的是要引用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">
@H_404_32@ <Grid>- <Grid.RowDeFinitions>
@H_404_32@ <RowDeFinition Height="Auto"></RowDeFinition>- </Grid.RowDeFinitions>
@H_404_32@ <Grid.ColumnDeFinitions>- <ColumnDeFinition Width="Auto"></ColumnDeFinition>
@H_404_32@ <ColumnDeFinition Width="*"></ColumnDeFinition>- </Grid.ColumnDeFinitions>
@H_404_32@ <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}">
@H_404_32@ <i:Interaction.Triggers>- <i:EventTrigger EventName="GotFocus">
@H_404_32@ <trigger:FocusTrigger></trigger:FocusTrigger>- </i:EventTrigger>
@H_404_32@ <i:EventTrigger EventName="LostFocus">- <trigger:LostFocusTrigger>
@H_404_32@ </trigger:LostFocusTrigger>- </i:EventTrigger>
@H_404_32@ </i:Interaction.Triggers>- </TextBox>
@H_404_32@ </Grid>- </Border>
这段代码是模拟了一个水印文本框效果,在这里使用到了Trigger,一个是FocusTrigger,一个是LostFocusTrigger,结合起来实现水印效果。我们看看这两个Trigger的代码
- public class FocusTrigger:TriggerAction<TextBox>
@H_404_32@ {- protected override void OnAttached()
@H_404_32@ {- base.OnAttached();
@H_404_32@ }- @H_404_32@ protected override void OnDetaching()
- {
@H_404_32@ base.OnDetaching();- }
@H_404_32@- protected override void Invoke(object parameter)
@H_404_32@ {- if (this.Associatedobject.Text.Trim() == "请输入用户名")
@H_404_32@ {- this.Associatedobject.Text = string.Empty;
@H_404_32@ this.Associatedobject.Foreground = new SolidColorBrush(Colors.Black);- }
@H_404_32@ }- }
这个是FocusTrigger,文本框获取焦点时,调用Invoke方法。这个时候当文本框的值是“请输入用户名”的时候,就清掉文本框,并且字体前景色设置为黑色。我们再看看LostFocusTrigger的代码
- public class LostFocusTrigger : TriggerAction<TextBox>
@H_404_32@ {- protected override void OnAttached()
@H_404_32@ {- base.OnAttached();
@H_404_32@ }- @H_404_32@ protected override void OnDetaching()
- {
@H_404_32@ base.OnDetaching();- }
@H_404_32@- protected override void Invoke(object parameter)
@H_404_32@ {- if (string.IsNullOrWhiteSpace(this.Associatedobject.Text))
@H_404_32@ {- this.Associatedobject.Foreground = new SolidColorBrush(Colors.Gray);
@H_404_32@ this.Associatedobject.Text = "请输入用户名";- }
@H_404_32@ }- }
当文本框失去焦点的时候,如果文本框值为空或者空白,那么文本框的值为“请输入用户名”,前景色改为Gray。OK,我们继续往下看
在这里我们使用了ComboBox的项模板,在这里你可以自定义你想要的模版。在这里我放了一个图片和一个文本。如下图所示
怎么样,很不错吧。最后在这列我们重点看看分页。我这可是服务端分页。
这个时候我就要把viewmodel的代码贴出来了,否则没法讲述清楚。
- namespace MISInfoManage.viewmodels
@H_404_32@{- public class UserManageviewmodel : INotifyPropertyChanged
@H_404_32@ {- private bool isFirstLoad;
@H_404_32@ public UserManageView userManageView;- DataPagerTrigger dataPagertrigger;
@H_404_32@ List<int> list = new List<int>();- public UserManageviewmodel()
@H_404_32@ {- this.InitData(1, 10);
@H_404_32@ }- @H_404_32@ public UserManageviewmodel(UserManageView userManageView)
- : this()
@H_404_32@ {- isFirstLoad = true;
@H_404_32@ this.userManageView = userManageView;- this.dataPagertrigger = new DataPagerTrigger(this);
@H_404_32@ this.AttachTrigger();- this.SetTitle();
@H_404_32@ this.UserNo = "请输入用户名";- }
@H_404_32@- #region property
@H_404_32@- /*此处省略部分代码*/ #endregion
@H_404_32@- @H_404_32@ #region method
- @H_404_32@ private void AttachTrigger()
- {
@H_404_32@ this.dataPagertrigger.Attach(this.userManageView.dataPager);- }
@H_404_32@- private void SetTitle()
@H_404_32@ {- Image image = new Image();
@H_404_32@ image.source = new BitmapImage(new Uri("../Images/drag.png", UriKind.Relative));- image.Height = 30;
@H_404_32@ image.Width = 20;- TextBlock textBlock = new TextBlock();
@H_404_32@ textBlock.Margin = new Thickness(5, 0, 0);- textBlock.Text = "用户管理";
@H_404_32@ textBlock.FontSize = 14;- textBlock.FontWeight = FontWeights.Bold;
@H_404_32@ StackPanel stackPanel = new StackPanel();- stackPanel.Orientation = Orientation.Horizontal;
@H_404_32@ stackPanel.Background = new RadialGradientBrush(Colors.Gray, Colors.brown);- stackPanel.Width = this.userManageView.Width;
@H_404_32@ stackPanel.Children.Add(image);- stackPanel.Children.Add(textBlock);
@H_404_32@ this.userManageView.Title = stackPanel;- }
@H_404_32@- private void GetUserList(UserRequest request, EventHandler<GetUserListCompletedEventArgs> callback)
@H_404_32@ {- UserManageService.UserManageServiceClient client = new UserManageServiceClient();
@H_404_32@ client.GetUserListCompleted += callback;- client.GetUserListAsync(request);
@H_404_32@ }- @H_404_32@ /*此处省略部分代码*/ @H_404_32@ @H_404_32@ @H_404_32@ private void GetUserPagedCollection(int totalCount)
- {
@H_404_32@ list.Clear();- for (int i = 0; i < totalCount; i++)
@H_404_32@ {- list.Add(i);
@H_404_32@ }- PagedCollectionView pagedCollectionView = new PagedCollectionView(list);
@H_404_32@ this.userManageView.dataPager.source = pagedCollectionView;- isFirstLoad = false;
@H_404_32@ }- @H_404_32@ public void GetDataByPage(int pageIndex, int pageSize)
- {
@H_404_32@ UserRequest userRequest = new UserRequest()- {
@H_404_32@ PageIndex = pageIndex,- PageSize = pageSize
@H_404_32@ };- this.GetUserList(userRequest, (obj, args) =>
@H_404_32@ {- if (args.Error == null)
@H_404_32@ {- this.UserResponse = args.Result;
@H_404_32@ this.UserList = userResponse.UserList;- if (isFirstLoad)
@H_404_32@ {- this.GetUserPagedCollection(this.UserResponse.RecordCount);
@H_404_32@ }- }
@H_404_32@ });- }
@H_404_32@- private void InitData(int pageIndex, int pageSize)
@H_404_32@ {- this.GetDataByPage(pageIndex,pageSize);
@H_404_32@ this.GetUserStateList();- this.GetUserTypeList();
@H_404_32@ }- @H_404_32@ #endregion
- @H_404_32@ /*此处省略部分代码*/ } @H_404_32@ @H_404_32@
- }
- this.dataPagertrigger = new DataPagerTrigger(this);
@H_404_32@ this.AttachTrigger();
这段代码就是在初始化viewmodel的时候,将dataPager控件附加给dataPagertrigger。我们看看dataPagertrigger代码
- public class DataPagerTrigger : TriggerBase<UIElement>
@H_404_32@ {- public UserManageviewmodel userManageviewmodel;
@H_404_32@ public DataPagerTrigger(UserManageviewmodel userManageviewmodel)- {
@H_404_32@ this.userManageviewmodel = userManageviewmodel;- }
@H_404_32@- protected override void OnAttached()
@H_404_32@ {- base.OnAttached();
@H_404_32@ if (this.Associatedobject is DataPager)- {
@H_404_32@ (this.Associatedobject as DataPager).PageIndexChanged += this.PageIndexChanged;- }
@H_404_32@ }- @H_404_32@ protected override void OnDetaching()
- {
@H_404_32@ base.OnDetaching();- if (this.Associatedobject is DataPager)
@H_404_32@ {- (this.Associatedobject as DataPager).PageIndexChanged -= this.PageIndexChanged;
@H_404_32@ }- }
@H_404_32@- private void PageIndexChanged(object sender, EventArgs e)
@H_404_32@ {- DataPager dataPager = sender as DataPager;
@H_404_32@ this.userManageviewmodel.GetDataByPage(dataPager.PageIndex, dataPager.PageSize);- }
@H_404_32@ }
这个类继承自TriggerBase,我们给其注册了一个PageIndexChanged 事件,当DataPager控件页码变化时,调用PageIndexChanged方法,在这个方法里调用userManageviewmodel的GetDataByPage方法。在GetDataByPage方法中先获取用户列表,判断如果是第一次加载,就给 DataPager控件附一个PagedCollectionView类型的一个source,在这里通过模拟,可以有效的进行分页,因为目前我发现这个分页控件只能客户端分页。所以模拟一个List<int>,它的总条数==表的总记录。这样就实现了服务端分页,如果谁想要源码,可以加入群205217091。我们看看分页的效果
最后大家可能注意到弹出界面的Title和以前的不一样,这里你可以自定义,如viewmodel中的SetTitle方法。好了,时间不早了,洗洗睡!
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。