扯面工程师,配菜工程师,门迎工程师,当今世界工程师可真多啊。
今天我们把系统参数管理模块翻译成Silverlight项目。首先请看两张图
再看看翻译好的图
其实我们看到了第二张图用到了treeView,Popup,这节主要讲的还是MVVM,不过和以往有所不同。先看看前台代码
- <controls:ChildWindow x:Class="MISInfoManage.CodeManageView"
- xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
- xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
- xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
- xmlns:toolkit="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls"
- xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"
- xmlns:resource="clr-namespace:MISInfoManage.Resources"
- xmlns:controls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls"
- xmlns:Primitives="clr-namespace:System.Windows.Controls.Primitives;assembly=System.Windows"
- mc:Ignorable="d" Width="700" Height="400" FontSize="13"
- Title="系统参数管理">
- <controls:ChildWindow.Resources>
- <resource:CodeManageResource x:Key="CodeManageResource"/>
- <Style x:Key="ColumnHeaderStyle" targettype="sdk:DataGridColumnHeader">
- <Setter Property="Height" Value="25"></Setter>
- </Style>
- </controls:ChildWindow.Resources>
- <Grid x:Name="LayoutRoot" Background="White">
- <Grid.RowDeFinitions>
- <RowDeFinition Height="*"></RowDeFinition>
- </Grid.RowDeFinitions>
- <Grid.ColumnDeFinitions>
- <ColumnDeFinition Width="Auto"></ColumnDeFinition>
- <ColumnDeFinition Width="*"></ColumnDeFinition>
- <ColumnDeFinition Width="0"></ColumnDeFinition>
- </Grid.ColumnDeFinitions>
- <Border BorderBrush="AliceBlue" Width="150" Grid.Row="0" Grid.Column="0" BorderThickness="1" CornerRadius="2" Margin="0,10,0">
- <toolkit:TreeView x:Name="treeViewCode"></toolkit:TreeView>
- </Border>
- <sdk:DataGrid Grid.Row="0" Grid.Column="1"
- BorderBrush="Black" BorderThickness="1"
- IsReadOnly="True" x:Name="dgCodeList"
- AutoGenerateColumns="False"
- AlternatingRowBackground="Gray"
- CanUserReorderColumns="True"
- VerticalScrollBarVisibility="Auto"
- HorizontalScrollBarVisibility="Auto"
- SelectionMode="Single"
- SelectedItem="{Binding CodeEntity,Mode=TwoWay}"
- ItemsSource="{Binding CodeList,Mode=OneWay}"
- CanUserSortColumns="True">
- <sdk:DataGrid.Columns>
- <sdk:DataGridTemplateColumn Header="选择">
- <sdk:DataGridTemplateColumn.CellTemplate>
- <DataTemplate>
- <CheckBox HorizontalAlignment="Center"></CheckBox>
- </DataTemplate>
- </sdk:DataGridTemplateColumn.CellTemplate>
- </sdk:DataGridTemplateColumn>
- <sdk:DataGridTextColumn Binding="{Binding data,Mode=OneWay}" HeaderStyle="{StaticResource ColumnHeaderStyle}" Header="数据值"/>
- <sdk:DataGridTextColumn Binding="{Binding ename,Mode=OneWay}" HeaderStyle="{StaticResource ColumnHeaderStyle}" Header="英文代码"/>
- <sdk:DataGridTextColumn Binding="{Binding cname,Mode=OneWay}" HeaderStyle="{StaticResource ColumnHeaderStyle}" Header="中文代码"/>
- <sdk:DataGridTextColumn Binding="{Binding display_content,Mode=OneWay}" HeaderStyle="{StaticResource ColumnHeaderStyle}" Header="显示值"/>
- <sdk:DataGridTemplateColumn Header="操作">
- <sdk:DataGridTemplateColumn.CellTemplate>
- <DataTemplate>
- <StackPanel>
- <StackPanel.Resources>
- <Style x:Key="buttonStyle" targettype="Button">
- <Setter Property="Template">
- <Setter.Value>
- <ControlTemplate targettype="Button">
- <Border CornerRadius="2" BorderThickness="1" BorderBrush="Red">
- <StackPanel Orientation="Horizontal" Background="Turquoise">
- <StackPanel.Effect>
- <DropShadowEffect Color="Black" Direction="270" ShadowDepth="5"
- BlurRadius="5" Opacity="0.5">
- </DropShadowEffect>
- </StackPanel.Effect>
- <Image Source="/MISInfoManage;component/Images/drag.png" Height="25" Width="60"/>
- <TextBlock Text="修改" Foreground="brown" FontWeight="Bold"></TextBlock>
- </StackPanel>
- </Border>
- </ControlTemplate>
- </Setter.Value>
- </Setter>
- </Style>
- </StackPanel.Resources>
- <Button Content="Button1" Style="{StaticResource buttonStyle}"/>
- </StackPanel>
- </DataTemplate>
- </sdk:DataGridTemplateColumn.CellTemplate>
- </sdk:DataGridTemplateColumn>
- </sdk:DataGrid.Columns>
- </sdk:DataGrid>
- <Primitives:Popup x:Name="CodeInfoPop" Grid.Row="0" Grid.Column="2">
- <StackPanel Width="200">
- <StackPanel.Style>
- <Style targettype="StackPanel">
- <Setter Property="Background" Value="brown"></Setter>
- </Style>
- </StackPanel.Style>
- <StackPanel.Effect>
- <DropShadowEffect
- Color="Black" Direction="300" ShadowDepth="10" BlurRadius="5" Opacity="0.6">
- </DropShadowEffect>
- </StackPanel.Effect>
- <StackPanel Orientation="Horizontal">
- <TextBlock Text="{Binding Tb_Ename,Source={StaticResource CodeManageResource}}"/>
- <TextBlock Text="{Binding CodeEntity.ename}" Margin="5,0"/>
- </StackPanel>
- <StackPanel Orientation="Horizontal">
- <TextBlock Text="{Binding Tb_CNm,Source={StaticResource CodeManageResource}}"/>
- <TextBlock Text="{Binding CodeEntity.cname}" Margin="5,0"/>
- </StackPanel>
- <StackPanel Orientation="Horizontal">
- <TextBlock Text="{Binding Tb_display,Source={StaticResource CodeManageResource}}"/>
- <TextBlock Text="{Binding CodeEntity.display_content}" Margin="5,0"/>
- </StackPanel>
- </StackPanel>
- </Primitives:Popup>
- </Grid>
- </controls:ChildWindow>
最普遍的布局方式Grid+StackPanel。记得上次好像我在写博客的时候,给每个控件都设置了FontSize,其实这个是没有必要的,只需要在controls:ChildWindow节点中设置,那么整个页面的控件的FontSize都起作用。再往下看,有这样的一些节点
<Style x:Key="buttonStyle" targettype="Button">...</Style>里面有这么一段代码
- <ControlTemplate targettype="Button">
- <Border CornerRadius="2" BorderThickness="1" BorderBrush="Red">
- <StackPanel Orientation="Horizontal" Background="Turquoise">
- <StackPanel.Effect>
- <DropShadowEffect Color="Black" Direction="270" ShadowDepth="5"
- BlurRadius="5" Opacity="0.5">
- </DropShadowEffect>
- </StackPanel.Effect>
- <Image Source="/MISInfoManage;component/Images/drag.png" Height="25" Width="60"/>
- <TextBlock Text="修改" Foreground="brown" FontWeight="Bold"></TextBlock>
- </StackPanel>
- </Border>
- </ControlTemplate>
这个是定义一个Button的控件模版。在这里我们给StackPanel定义了一个特效DropShadowEffect ,一个阴影效果。在这个模板中我放置了一个图片和一个文本,大家看看上面的图就知道了。整个一按钮变成如此摸样,所以在我们做开发的时候,可以通过设置ControlTemplate来定制我们按钮或者其他控件的模版。在按钮中,我们只需要设置Style="{StaticResource buttonStyle}"即可。再往下走,有这么一段代码
<Primitives:Popup x:Name="CodeInfoPop" Grid.Row="0" Grid.Column="2">这个节点正是定义我们的Popup,当DataGrid的SelectionChanged触发时,弹出Popup。注意Popup这里需要引用System.Windows.Controls.Primitives。好了前台没什么,就这么些。我们看看页面后台,代码如下
- namespace MISInfoManage
- {
- public partial class CodeManageView : ChildWindow
- {
- CodeManageModel codeManage;
- public CodeManageView()
- {
- InitializeComponent();
- codeManage = new CodeManageModel(this);
- this.LayoutRoot.DataContext = codeManage;
- }
- }
- }
我勒了个去,怎么就这么点代码,我告诉你,就这么点代码。我们这次使用了Behavior,那么就不会出现页面后台事件。看看viewmodel到底都干了些什么。
- namespace MISInfoManage.viewmodels
- {
- public class CodeManageModel : INotifyPropertyChanged
- {
- public ChildWindow userControl;
- CodeManageServiceClient client;
- SelectionChangedBehavior mouseRightButtonBrhavior;
- public CodeManageModel()
- {
- client = new CodeManageServiceClient();
- this.GetCodesList((obj, args) =>
- {
- this.CodesList = args.Result;
- this.BuildTree();
- });
- }
- public CodeManageModel(ChildWindow userControl)
- : this()
- {
- this.userControl = userControl;
- this.mouseRightButtonBrhavior = new SelectionChangedBehavior(this);
- mouseRightButtonBrhavior.Attach((userControl as CodeManageView).dgCodeList);
- this.SetContextMenu();
- }
- private List<Codes> codesList;
- public List<Codes> CodesList
- {
- get
- {
- return codesList;
- }
- set
- {
- codesList = value;
- NotifyPropertyChange("CodesList");
- }
- }
- private List<Codes> codeList;
- public List<Codes> CodeList
- {
- get
- {
- return codeList;
- }
- set
- {
- codeList = value;
- NotifyPropertyChange("CodeList");
- }
- }
- private Codes codeEntity;
- public Codes CodeEntity
- {
- set
- {
- codeEntity = value;
- NotifyPropertyChange("CodeEntity");
- }
- get
- {
- return codeEntity;
- }
- }
- public void GetCodesList(EventHandler<GetCodeListCompletedEventArgs> handler)
- {
- client.GetCodeListCompleted += handler;
- client.GetCodeListAsync();
- }
- public void GetCodeListByCondition(string ename, EventHandler<GetCodeListByConditionCompletedEventArgs> handler)
- {
- client.GetCodeListByConditionCompleted += handler;
- client.GetCodeListByConditionAsync(ename);
- }
- public void BuildTree()
- {
- TreeViewItem mainitem = new TreeViewItem();
- mainitem.Header = "系统参数";
- mainitem.IsExpanded = true;
- List<Codes> codeList = null;
- if (this.CodesList != null && this.CodesList.Count > 0)
- {
- codeList = this.CodesList.distinct<Codes>(new EqualityCompare()).ToList();
- codeList.ForEach(c =>
- {
- TreeViewItem treeViewItem = new TreeViewItem();
- StackPanel stackPanel = new StackPanel();
- stackPanel.Orientation = Orientation.Horizontal;
- TextBlock textBlock = new TextBlock();
- textBlock.Text = c.cname;
- textBlock.Tag = c.ename;
- textBlock.MouseLeftButtonDown += this.LoadCodeByID;
- Image image = new Image();
- image.Width = 12;
- image.Height = 12;
- image.Margin = new Thickness(0, 0, 5, 0);
- image.source = new BitmapImage(new Uri("../Images/Windows.jpg", UriKind.Relative));
- stackPanel.Children.Add(image);
- stackPanel.Children.Add(textBlock);
- treeViewItem.Header = stackPanel;
- mainitem.Items.Add(treeViewItem);
- });
- (this.userControl as CodeManageView).treeViewCode.Items.Add(mainitem);
- }
- }
- private void LoadCodeByID(object sender, MouseButtonEventArgs e)
- {
- TextBlock textBlock = sender as TextBlock;
- string ename = textBlock.Tag.ToString();
- this.GetCodeListByCondition(ename, (obj, args) =>
- {
- this.CodeList = args.Result;
- });
- }
- private void SetContextMenu()
- {
- ContextMenu contextMenu = new ContextMenu();
- MenuItem menuItem = new MenuItem();
- menuItem.Tag = "Modify";
- TextBlock textBlock = new TextBlock();
- textBlock.Text = "修改";
- menuItem.Header = textBlock;
- contextMenu.Items.Add(menuItem);
- menuItem = new MenuItem();
- textBlock = new TextBlock();
- textBlock.Text = "添加";
- menuItem.Tag = "Add";
- menuItem.Header = textBlock;
- contextMenu.Items.Add(menuItem);
- menuItem = new MenuItem();
- textBlock = new TextBlock();
- textBlock.Text = "关闭";
- menuItem.Tag = "Close";
- menuItem.Header = textBlock;
- menuItem.Click += delegate(object sender, RoutedEventArgs e)
- {
- (userControl as CodeManageView).Close();
- };
- contextMenu.Items.Add(menuItem);
- ContextMenuService.SetContextMenu((this.userControl as CodeManageView).dgCodeList, contextMenu);
- }
- public event PropertyChangedEventHandler PropertyChanged;
- private void NotifyPropertyChange(string property)
- {
- if (PropertyChanged != null)
- {
- PropertyChanged(this, new PropertyChangedEventArgs(property));
- }
- }
- }
- public class EqualityCompare : IEqualityComparer<Codes>
- {
- public bool Equals(Codes code1, Codes code2)
- {
- return code1.ename.Equals(code2.ename);
- }
- public int GetHashCode(Codes code)
- {
- return code.ename.GetHashCode();
- }
- }
- }
首先进入构造函数,初始化我们的TreeView,初始化TreeView的时候有这么个代码codeList = this.CodesList.distinct<Codes>(new EqualityCompare()).ToList();去除List<T>重复。我们知道对象的值都一样,不代表对象一样。所以我们需要实现IEqualityComparer<T>接口,Equals方法确定你要distinct的规则,在这里就是Ename不相等。GetHashCode必须返回Ename的HashCode。再往下走,这么一段代码
- this.mouseRightButtonBrhavior = new SelectionChangedBehavior(this);
- mouseRightButtonBrhavior.Attach((userControl as CodeManageView).dgCodeList);
在这里使用到了Behavior,我们为DataGrid定义了一个行为,我们来看看这个行为
- namespace MISInfoManage.Behavior
- {
- public class SelectionChangedBehavior : Behavior<DataGrid>
- {
- CodeManageModel _codeManageModel;
- public SelectionChangedBehavior():base()
- {}
- public SelectionChangedBehavior(CodeManageModel codeManageModel)
- : this()
- {
- _codeManageModel = codeManageModel;
- }
- protected override void OnAttached()
- {
- base.OnAttached();
- this.Associatedobject.SelectionChanged += Associatedobject_SelectionChanged;
- this.Associatedobject.MouseMove += Associatedobject_MouseMove;
- }
- protected override void OnDetaching()
- {
- base.OnDetaching();
- this.Associatedobject.SelectionChanged -= Associatedobject_SelectionChanged;
- this.Associatedobject.MouseMove -= Associatedobject_MouseMove;
- }
- private void Associatedobject_SelectionChanged(object sender, SelectionChangedEventArgs e)
- {
- if (_codeManageModel.CodeEntity != null)
- {
- Popup popup = (this._codeManageModel.userControl as CodeManageView).CodeInfoPop;
- popup.HorizontalOffset = 20;
- popup.VerticalOffset = 70;
- popup.IsOpen = true;
- }
- }
- private void Associatedobject_MouseMove(object sender,MouseEventArgs e)
- {
- Popup popup = (this._codeManageModel.userControl as CodeManageView).CodeInfoPop;
- popup.IsOpen = false;
- }
- }
- }
- namespace System.Windows.Interactivity
- {
- // Summary:
- // Encapsulates state @R_708_4045@ion and zero or more ICommands into an attachable
- // object.
- //
- // Type parameters:
- // T:
- // The type the System.Windows.Interactivity.Behavior<T> can be attached to.
- //
- // Remarks:
- // Behavior is the base class for providing attachable state and commands to
- // an object. The types the Behavior can be attached to can be controlled by
- // the generic parameter. Override OnAttached() and OnDetaching() methods to
- // hook and unhook any necessary handlers from the Associatedobject.
- public abstract class Behavior<T> : Behavior where T : System.Windows.DependencyObject
- {
- // Summary:
- // Initializes a new instance of the System.Windows.Interactivity.Behavior<T>
- // class.
- protected Behavior();
- // Summary:
- // Gets the object to which this System.Windows.Interactivity.Behavior<T> is
- // attached.
- protected T Associatedobject { get; }
- }
- }
这里的的Associatedobject就是泛型T,并且它是System.Windows.DependencyObject类型的。Behavior类是个抽象类,具有Attach,Detach,OnAttached,OnDetaching方法。OnAttached在Attach方法调用以后生效。所以这段代码就实现了DataGrid的SelectionChanged和MouseMove事件,在SelectionChanged以后弹出Popup,MouseMove以后隐藏Popup。这种方式是不是很有效的实现了页面UI和逻辑的分离。再往下走,有个SetContextMenu方法,正是给DataGrid附加一个弹出菜单。在菜单构造好以后,需要调用ContextMenuService.SetContextMenu((this.userControl as CodeManageView).dgCodeList,contextMenu);,第一个参数是一个DependencyObject类型的对象,第二个是ContextMenu对象。类似于这样的内置对象还有FocusManager,它的方法FocusManager.GetFocusedElement()可以直接找到页面获得焦点的元素。我们来看看这个菜单的效果,
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。