赞
踩
这次的需求是:有一所学校,为了方便了解学校里所有班级的情况(这里就看各位想定义哪些情况了),故需要设计出一个在界面上既能查看每个班级中每个学生的信息,又能展示每个班级的总体情况。
我分析的是:结合前面所讲述的知识点,查看每个班级用TreeView,展示总体情况用DataGrid。那就动手看看吧
先看项目结构(注意个模块得统一:要么用core,要么用Framework)
接下来逐一讲述
(1)common模块
枚举(Enums):就一个枚举(节点类型)
- public enum NodeType
- {
- [Description("班级")]
- Grade,
-
- [Description("学生")]
- Student,
- }
转换器(Converts):从枚举的值判断后返回是否显示(上代码)
- public class EnumToVisibilityConvert : IValueConverter
- {
- public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
- {
- if (value is Enum enumValue)
- {
- switch (enumValue)
- {
- case NodeType.Grade:
- return Visibility.Collapsed;
- case NodeType.Student:
- return Visibility.Visible;
- default:
- return Visibility.Collapsed;
- }
- }
- return Visibility.Collapsed;
- }
-
- public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
- {
- return value;
- }
- }
命令(DelegateCommand),这个就不做概述了,之前用的都是它,不知道的可以看我前面的文章
对象(Models):就一个主体对象,树结构加附属对象——学生结构(看代码,BindableObject不讲述了,跟命令一样的,前面文章有)
- public abstract class BaseModel : BindableObject
- {
- public virtual string Name { get; set; }
-
- public virtual Guid Guid { get; set; }
-
- public virtual NodeType Node { get; set; } = NodeType.Grade;
- }
- public class TreeModel : BaseModel
- {
- private ObservableCollection<StudentInfo> student = new ObservableCollection<StudentInfo>();
-
- public ObservableCollection<StudentInfo> Student
- {
- get => student;
- set
- {
- student = value;
- OnPropertyChanged();
- }
- }
-
- }
- public class StudentInfo : BaseModel
- {
- private string gender;
-
- public string Gender
- {
- get => gender;
- set
- {
- gender = value;
- OnPropertyChanged();
- }
- }
-
- private int age;
-
- public int Age
- {
- get => age;
- set
- {
- age = value;
- OnPropertyChanged();
- }
- }
-
- private string address;
-
- public string Address
- {
- get => address;
- set
- {
- address = value;
- OnPropertyChanged();
- }
- }
-
- private string number;
-
- public string Number
- {
- get => number;
- set
- {
- number = value;
- OnPropertyChanged();
- }
- }
-
- }
管理者(TreeViewManager):管理整个TreeView的逻辑交互(这次的封装不太好,大部分的逻辑,ViewModel那里就实现了,都没到这管理库来——哈哈哈,应该是我想偷懒,不想提取了)
- public class TreeViewManager : TreeViewInterface
- {
- private static ObservableCollection<TreeModel> treeModels = new ObservableCollection<TreeModel>();
-
- public static ObservableCollection<TreeModel> TreeModels
- {
- get => treeModels;
- set
- {
- treeModels = value;
- OnTreeModelsChanged();
- }
- }
-
- public static event EventHandler TreeModelsChanged;
- public static void OnTreeModelsChanged()
- {
- TreeModelsChanged?.Invoke(TreeModels, new EventArgs());
- }
-
- public void InitTree()
- {
- TreeModel treeModel = new TreeModel()
- {
- Guid = Guid.NewGuid(),
- Name = "三年级二班",
- Node = Enums.NodeType.Grade
- };
-
- StudentInfo student = new StudentInfo()
- {
- Name = "小红",
- Guid = treeModel.Guid,
- Age = 8,
- Gender = "女",
- Address = "天河路",
- Node = Enums.NodeType.Student,
- Number = "111111"
- };
-
- treeModel.Student.Add(student);
-
- student = new StudentInfo()
- {
- Name = "小明",
- Guid = treeModel.Guid,
- Age = 8,
- Gender = "男",
- Address = "尧新路",
- Node = Enums.NodeType.Student,
- Number = "222222"
- };
-
- treeModel.Student.Add(student);
-
- student = new StudentInfo()
- {
- Name = "小黑",
- Guid = treeModel.Guid,
- Age = 7,
- Gender = "男",
- Address = "水西路",
- Node = Enums.NodeType.Student,
- Number = "333333"
- };
-
- treeModel.Student.Add(student);
-
- TreeModels.Add(treeModel);
- }
-
- }
(2)interface模块
就一个,目录树的接口,对应一些方法(我这就只有一个方法。。。哈哈哈)
- public interface TreeViewInterface
- {
- void InitTree();
- }
(2)VM-V模块
VM模块:一个是表格的,一个是目录树的,直接看代码吧
- public class DataGridViewModel : BindableObject
- {
- private TreeModel treeModel;
-
- public TreeModel TreeModel
- {
- get => treeModel;
- set
- {
- treeModel = value;
- OnPropertyChanged();
- }
- }
-
- public DataGridViewModel(TreeModel model)
- {
- this.TreeModel = model;
- }
- }
- public class TreeViewModel : BindableObject
- {
- private readonly TreeViewInterface @interface;
-
- public ObservableCollection<TreeModel> TreeModels => TreeViewManager.TreeModels;
-
- private TreeModel treeModel;
-
- public TreeModel TreeModel
- {
- get => treeModel;
- set
- {
- treeModel = value;
- OnPropertyChanged();
- }
- }
-
-
- private StudentInfo student;
-
- public StudentInfo Student
- {
- get => student;
- set
- {
- student = value;
- OnPropertyChanged();
- }
- }
-
- private BaseModel baseModel;
-
- public BaseModel BaseModel
- {
- get => baseModel;
- set
- {
- baseModel = value;
- OnPropertyChanged();
- }
- }
-
- public DelegateCommand<TreeView> SelectChangeCommand { get; private set; }
-
- public DelegateCommand<TreeModel> OpenTableCommand { get; private set; }
-
- public TreeViewModel(TreeViewInterface @interface)
- {
- this.@interface = @interface;
- this.SelectChangeCommand = new DelegateCommand<TreeView>(SelectChange);
- OpenTableCommand = new DelegateCommand<TreeModel>(OpenTable);
- InitTree();
- }
-
- #region 命令
- public void OpenTable(TreeModel model)
- {
- var win = new DataGridView(model);
- win.Show();
- }
- #endregion
-
- #region 事件
- public void SelectChange(TreeView tree)
- {
- BaseModel = (BaseModel)tree.SelectedItem;
- JudgeNode();
- }
- #endregion
-
- #region 方法
- private void InitTree()
- {
- this.@interface.InitTree();
- BaseModel = TreeModels[0];
- }
-
- private void JudgeNode()
- {
- switch (BaseModel.Node)
- {
- case TreeViewChangeDataGrid.Common.Enums.NodeType.Grade:
- TreeModel = (TreeModel)BaseModel;
- break;
- case TreeViewChangeDataGrid.Common.Enums.NodeType.Student:
- Student = (StudentInfo)BaseModel;
- break;
- default:
- break;
- }
- }
- #endregion
V模块:一个是表格的,一个是目录树的(记得安装之前讲过的behavior的包)
a、树的界面,这次我用了之前没讲过的方法,这次树不是递归的结构,所有要么用我第一篇文章那样绑定(那方法有点老套了),要么就换一种方法(看图)
这就是新的绑定方法,跟之前很像,只是多了一个DataType,用来指定绑定的结构类型的(看代码)
- <Window
- x:Class="TreeViewChangeDataGrid.Views.TreeView"
- xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
- xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- xmlns:convert="clr-namespace:TreeViewChangeDataGrid.Common.Converts;assembly=TreeViewChangeDataGrid.Common"
- xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
- xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
- xmlns:local="clr-namespace:TreeViewChangeDataGrid.Views"
- xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
- xmlns:model="clr-namespace:TreeViewChangeDataGrid.Common.Models;assembly=TreeViewChangeDataGrid.Common"
- Title="MainView"
- Width="800"
- Height="450"
- mc:Ignorable="d">
- <Window.Resources>
-
- <convert:EnumToVisibilityConvert x:Key="enumToVisibilityConvert" />
-
- <!-- 右键菜单 -->
- <ContextMenu x:Key="Custom">
- <MenuItem Header="表格查看">
- <i:Interaction.Triggers>
- <i:EventTrigger EventName="Click">
- <i:InvokeCommandAction Command="{Binding DataContext.OpenTableCommand, RelativeSource={RelativeSource AncestorType=Window, Mode=FindAncestor}}" CommandParameter="{Binding}" />
- </i:EventTrigger>
- </i:Interaction.Triggers>
- </MenuItem>
- </ContextMenu>
- <!-- 右键菜单 -->
-
- <HierarchicalDataTemplate DataType="{x:Type model:TreeModel}" ItemsSource="{Binding Student}">
- <Grid>
- <TextBlock Text="{Binding Name}" />
- <Grid.Style>
- <Style TargetType="Grid">
- <Setter Property="ContextMenu" Value="{StaticResource Custom}" />
- </Style>
- </Grid.Style>
- </Grid>
- </HierarchicalDataTemplate>
- <HierarchicalDataTemplate DataType="{x:Type model:StudentInfo}">
- <Grid>
- <TextBlock Text="{Binding Name}" />
- </Grid>
- </HierarchicalDataTemplate>
- </Window.Resources>
- <Grid Margin="10">
- <Grid.ColumnDefinitions>
- <ColumnDefinition Width="200" />
- <ColumnDefinition />
- </Grid.ColumnDefinitions>
- <TreeView x:Name="tree" ItemsSource="{Binding TreeModels}">
- <i:Interaction.Triggers>
- <i:EventTrigger EventName="SelectedItemChanged">
- <i:InvokeCommandAction Command="{Binding DataContext.SelectChangeCommand, RelativeSource={RelativeSource AncestorType=Window, Mode=FindAncestor}}" CommandParameter="{Binding ElementName=tree}" />
- </i:EventTrigger>
- </i:Interaction.Triggers>
- </TreeView>
- <StackPanel
- Grid.Column="1"
- VerticalAlignment="Center"
- Visibility="{Binding BaseModel.Node, Converter={StaticResource enumToVisibilityConvert}}">
- <StackPanel HorizontalAlignment="Center" Orientation="Horizontal">
- <Label Margin="0,0,20,0" Content="姓名:" />
- <TextBox
- Width="100"
- VerticalContentAlignment="Center"
- Text="{Binding Student.Name}" />
- </StackPanel>
- <StackPanel
- Margin="0,20"
- HorizontalAlignment="Center"
- Orientation="Horizontal">
- <Label Margin="0,0,20,0" Content="年龄:" />
- <TextBox
- Width="100"
- VerticalContentAlignment="Center"
- Text="{Binding Student.Age}" />
- </StackPanel>
- <StackPanel HorizontalAlignment="Center" Orientation="Horizontal">
- <Label Margin="0,0,20,0" Content="性别:" />
- <TextBox
- Width="100"
- VerticalContentAlignment="Center"
- Text="{Binding Student.Gender}" />
- </StackPanel>
- <StackPanel
- Margin="0,20"
- HorizontalAlignment="Center"
- Orientation="Horizontal">
- <Label Margin="0,0,20,0" Content="地址:" />
- <TextBox
- Width="100"
- VerticalContentAlignment="Center"
- Text="{Binding Student.Address}" />
- </StackPanel>
- <StackPanel HorizontalAlignment="Center" Orientation="Horizontal">
- <Label Margin="0,0,20,0" Content="电话:" />
- <TextBox
- Width="100"
- VerticalContentAlignment="Center"
- Text="{Binding Student.Number}" />
- </StackPanel>
- </StackPanel>
- </Grid>
- </Window>
b、表格的界面,从外到里设置,一次是DataGrid、Column、Row、Cell的样式,而对于列数据的绑定,我用的是DataGridTemplateColumn,直接看代码
- <Grid>
- <ScrollViewer
- Margin="10"
- HorizontalScrollBarVisibility="Auto"
- PreviewMouseWheel="PreviewMouseWheel"
- VerticalScrollBarVisibility="Auto">
- <DataGrid
- HorizontalAlignment="Center"
- AutoGenerateColumns="False"
- Background="#fff"
- BorderBrush="Transparent"
- CanUserAddRows="False"
- GridLinesVisibility="None"
- HorizontalScrollBarVisibility="Hidden"
- IsReadOnly="True"
- ItemsSource="{Binding DataContext.TreeModel.Student, RelativeSource={RelativeSource AncestorType=Window, Mode=FindAncestor}}">
-
- <!--#region 设置列的个数-->
- <DataGrid.Style>
- <Style TargetType="DataGrid">
- <Setter Property="HeadersVisibility" Value="Column" />
- </Style>
- </DataGrid.Style>
- <!--#endregion-->
-
- <!--#region 数据网格的列标题样式属性-->
- <DataGrid.ColumnHeaderStyle>
- <!-- 样式类型:DataGridColumnHeader(数据网格列标题) -->
- <Style TargetType="{x:Type DataGridColumnHeader}">
- <Setter Property="Height" Value="74" />
- <Setter Property="BorderThickness">
- <Setter.Value>
- <Thickness
- Bottom="1"
- Left="1"
- Right="1"
- Top="1" />
- </Setter.Value>
- </Setter>
- <Setter Property="Background" Value="Orange" />
- <Setter Property="BorderBrush" Value="Green" />
- <Setter Property="HorizontalContentAlignment" Value="Center" />
- <Setter Property="FontFamily" Value="微软雅黑" />
- <Setter Property="FontWeight" Value="Black" />
- <Setter Property="FontSize" Value="14" />
- </Style>
- </DataGrid.ColumnHeaderStyle>
- <!--#endregion-->
-
- <!--#region DataGrid的RowStyle属性-->
- <DataGrid.RowStyle>
- <Style TargetType="DataGridRow">
- <Setter Property="Background" Value="LightBlue" />
- </Style>
- </DataGrid.RowStyle>
- <!--#endregion-->
-
- <!--#region DataGrid的CellStyle属性(数据表格的单元格样式)-->
- <DataGrid.CellStyle>
- <Style TargetType="DataGridCell">
- <Setter Property="BorderThickness">
- <Setter.Value>
- <Thickness
- Bottom="1"
- Left="1"
- Right="1" />
- </Setter.Value>
- </Setter>
- <Setter Property="BorderBrush" Value="Green" />
- <Style.Triggers>
- <Trigger Property="IsSelected" Value="True">
- <Setter Property="Background">
- <Setter.Value>
- <SolidColorBrush Opacity="0.9" Color="AntiqueWhite" />
- </Setter.Value>
- </Setter>
- <Setter Property="Foreground" Value="Red" />
- </Trigger>
- </Style.Triggers>
- </Style>
- </DataGrid.CellStyle>
- <!--#endregion-->
-
- <DataGrid.Columns>
- <!--#region 姓名-->
- <DataGridTemplateColumn Header="姓名">
- <DataGridTemplateColumn.CellTemplate>
- <DataTemplate>
- <StackPanel
- Margin="20"
- HorizontalAlignment="Center"
- VerticalAlignment="Center"
- Orientation="Horizontal">
- <TextBlock Text="{Binding Name}" />
- </StackPanel>
- </DataTemplate>
- </DataGridTemplateColumn.CellTemplate>
- </DataGridTemplateColumn>
- <!--#endregion-->
-
- <!--#region 年龄-->
- <DataGridTemplateColumn Header="年龄">
- <DataGridTemplateColumn.CellTemplate>
- <DataTemplate>
- <StackPanel
- Margin="20"
- HorizontalAlignment="Center"
- VerticalAlignment="Center"
- Orientation="Horizontal">
- <TextBlock Text="{Binding Age}" />
- </StackPanel>
- </DataTemplate>
- </DataGridTemplateColumn.CellTemplate>
- </DataGridTemplateColumn>
- <!--#endregion-->
-
- <!--#region 性别-->
- <DataGridTemplateColumn Header="性别">
- <DataGridTemplateColumn.CellTemplate>
- <DataTemplate>
- <StackPanel
- Margin="20"
- HorizontalAlignment="Center"
- VerticalAlignment="Center"
- Orientation="Horizontal">
- <TextBlock Text="{Binding Gender}" />
- </StackPanel>
- </DataTemplate>
- </DataGridTemplateColumn.CellTemplate>
- </DataGridTemplateColumn>
- <!--#endregion-->
-
- <!--#region 地址-->
- <DataGridTemplateColumn Header="地址">
- <DataGridTemplateColumn.CellTemplate>
- <DataTemplate>
- <StackPanel
- Margin="20"
- HorizontalAlignment="Center"
- VerticalAlignment="Center"
- Orientation="Horizontal">
- <TextBlock Text="{Binding Address}" />
- </StackPanel>
- </DataTemplate>
- </DataGridTemplateColumn.CellTemplate>
- </DataGridTemplateColumn>
- <!--#endregion-->
-
- <!--#region 地址-->
- <DataGridTemplateColumn Header="电话">
- <DataGridTemplateColumn.CellTemplate>
- <DataTemplate>
- <StackPanel
- Margin="20"
- HorizontalAlignment="Center"
- VerticalAlignment="Center"
- Orientation="Horizontal">
- <TextBlock Text="{Binding Number}" />
- </StackPanel>
- </DataTemplate>
- </DataGridTemplateColumn.CellTemplate>
- </DataGridTemplateColumn>
- <!--#endregion-->
- </DataGrid.Columns>
- </DataGrid>
- </ScrollViewer>
- </Grid>
总体思路是目录树显示个体信息,右键打开表格看总体信息,运行效果看图
(1)这次的案例并不算是典型案例,我自己随意想的,只是为了扩展下思路;
(2)目录树我没有添加其他的功能,感兴趣的可以自行看我之前的文章扩展功能;
(3)这次的案例需求简单,所以实现起来简单,如果是项目上,会有动态添加新的列,添加按钮,右键菜单等等;(后面感兴趣的可以跟我交流)
(4)下次我想换个玩法了,从数据库中提取数据来渲染,不想每次的造数据,具体容我想想
(5)这次案例的源码:GitHub - TQtong/TreeViewChangeDataGrid
这次的文章就到这了, 那么我继续闯荡江湖了,希望各位指出不足之处,
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。