ToB企服应用市场:ToB评测及商务社交产业平台

标题: 如何基于WPF写一款数据库文档管理工具(二) [打印本页]

作者: 惊落一身雪    时间: 2022-9-6 10:14
标题: 如何基于WPF写一款数据库文档管理工具(二)
系列目录

基于WPF重复造轮子,写一款数据库文档管理工具(一)
本篇重点

上次发表了基于WPF重复造轮子,写一款数据库文档管理工具(一) 得到不少人支持,文章一度上到了博客园推荐表首页,看来大家对这个工具还是很喜欢。今天就继续来分享一下我在开发这款工具的过程中积累的一些技术点。
本篇主要讲的是基于HandyControl控件的DataGrid进行数据绑定以及如何实现自定义一个自定义控件。在写这些之前我们先来看下我们工具的整个界面:

今天我们要实现的就是右边主界面展示的列表区域,其实这个区域是由多个用户控件组成的。下面截图就是列表区域的外层布局。

在这里我们也可以直接定义一个用户控件,然后使用MVVM的模式根据不同的类型展示不同的用户控件内容。
一.用户控件

下面贴一下我们用户控件的具体实现代码:
点击查看代码
  1. <local:BaseUserControl
  2.     x:
  3.     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  4.     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  5.     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  6.     xmlns:hc="https://handyorg.github.io/handycontrol"
  7.     xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
  8.     xmlns:local="clr-namespace:SmartSQL.UserControl"
  9.     xmlns:localBase="clr-namespace:SmartSQL.UserControl.Controls"
  10.     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  11.     mc:Ignorable="d">
  12.     <Grid Background="#f5f5f5">
  13.         
  14.         <hc:SearchBar
  15.             x:Name="SearchObject"
  16.             Height="30"
  17.             Margin="5,5,5,0"
  18.             Padding="5,0,5,0"
  19.             VerticalAlignment="Top"
  20.             HorizontalContentAlignment="Left"
  21.             hc:InfoElement.Placeholder="{Binding Placeholder}"
  22.             FontSize="13"
  23.             ShowClearButton="True"
  24.             
  25.             TextChanged="SearchObject_OnTextChanged" />
  26.         
  27.         <DataGrid
  28.             x:Name="TableGrid"
  29.             Margin="0,38,0,32"
  30.             hc:DataGridAttach.CanUnselectAllWithBlankArea="True"
  31.             hc:DataGridAttach.ShowRowNumber="True"
  32.             AutoGenerateColumns="False"
  33.             Background="Transparent"
  34.             BeginningEdit="TableGrid_OnBeginningEdit"
  35.             CellEditEnding="TableGrid_OnCellEditEnding"
  36.             ColumnWidth="*"
  37.             HeadersVisibility="All"
  38.             ItemsSource="{Binding ObjectsViewData, Mode=TwoWay}"
  39.             MouseDoubleClick="TableGrid_OnMouseDoubleClick"
  40.             MouseLeftButtonUp="TableGrid_OnMouseLeftButtonUp"
  41.             RowHeaderWidth="60"
  42.             SelectionUnit="CellOrRowHeader">
  43.             <DataGrid.CellStyle>
  44.                
  45.             </DataGrid.CellStyle>
  46.             <DataGrid.Columns>
  47.                 <DataGridCheckBoxColumn
  48.                     Width="60"
  49.                     Binding="{Binding IsChecked}"
  50.                     CanUserSort="False"
  51.                     Cell
  52.                     Header="选择" />
  53.                 <DataGridTextColumn
  54.                     x:Name="ObjHead"
  55.                     Binding="{Binding DisplayName}"
  56.                     Header="对象名"
  57.                     IsReadOnly="True" />
  58.                 <DataGridTextColumn
  59.                     Binding="{Binding Comment}"
  60.                     CanUserSort="False"
  61.                     Header="备注说明" />
  62.                 <DataGridTextColumn
  63.                     Binding="{Binding CreateDate, StringFormat='yyyy-MM-dd'}"
  64.                     Cell
  65.                     Header="创建时间"
  66.                     IsReadOnly="True" />
  67.                 <DataGridTextColumn
  68.                     Binding="{Binding ModifyDate, StringFormat='yyyy/MM/dd'}"
  69.                     Cell
  70.                     Header="修改时间"
  71.                     IsReadOnly="True" />
  72.             </DataGrid.Columns>
  73.         </DataGrid>
  74.         <Grid
  75.             x:Name="NoDataText"
  76.             Margin="5,45,5,37"
  77.             HorizontalAlignment="Stretch"
  78.             Background="White"
  79.             Cursor="Arrow">
  80.             <localBase:NoDataArea
  81.                 Margin="0"
  82.                 HorizontalAlignment="Center"
  83.                 ShowType="Img" />
  84.         </Grid>
  85.         <Grid
  86.             Height="36"
  87.             VerticalAlignment="Bottom"
  88.             Background="White"
  89.             Cursor="Arrow">
  90.             <hc:SimpleStackPanel
  91.                 Margin="47,0,5,10"
  92.                 HorizontalAlignment="Left"
  93.                 VerticalAlignment="Bottom">
  94.                 <hc:UniformSpacingPanel Spacing="10">
  95.                     <CheckBox
  96.                         x:Name="ChkAll"
  97.                         Margin="39,0,0,0"
  98.                         Click="ChkAll_OnClick"
  99.                         Content="全选" />
  100.                 </hc:UniformSpacingPanel>
  101.             </hc:SimpleStackPanel>
  102.             <hc:SimpleStackPanel
  103.                 Margin="5,0,5,5"
  104.                 HorizontalAlignment="Right"
  105.                 VerticalAlignment="Bottom">
  106.                 <hc:UniformSpacingPanel Spacing="10">
  107.                     <Button
  108.                         x:Name="BtnSetGroup"
  109.                         Height="26"
  110.                         hc:IconElement.Geometry="{StaticResource SetGroupGeometry}"
  111.                         Click="BtnSetGroup_OnClick"
  112.                         Content="设置分组"
  113.                         Cursor="Hand"
  114.                          />
  115.                     <Button
  116.                         x:Name="BtnExport"
  117.                         Height="26"
  118.                         hc:IconElement.Geometry="{StaticResource ExportGeometry}"
  119.                         Click="BtnExport_OnClick"
  120.                         Content="导出文档"
  121.                         Cursor="Hand"
  122.                          />
  123.                     
  124.                 </hc:UniformSpacingPanel>
  125.             </hc:SimpleStackPanel>
  126.         </Grid>
  127.     </Grid>
  128. </local:BaseUserControl>
复制代码
然后再具体使用的页面按照下面这样写就可以实现一个用户控件的嵌入了:
  1. [/code][size=4]二.用户控件数据传递[/size]
  2. 虽然页面是嵌入成功了,我们要实现点击左边菜单的数据表然后加载对应表的列表内容该怎么做呢?
  3. 其实我这里做了两层嵌套,外面第一层主窗口,中间还有一层用户控件MainW.xaml,然后才是加载数据列表的MainObjects.xaml,下面来看看我们后台代码的实现:
  4. [code]        /// <summary>
  5.         /// 选中表加载主内容对应数据
  6.         /// </summary>
  7.         /// <param name="sender"></param>
  8.         /// <param name="e"></param>
  9.         private void SelectedTable_OnClick(object sender, RoutedEventArgs e)
  10.         {
  11.             #region MyRegion
  12.             var selectDatabase = (DataBase)SelectDatabase.SelectedItem;
  13.             if (!(TreeViewTables.SelectedItem is TreeNodeItem objects) || objects.Type == ObjType.Group || objects.TextColor.Equals("Red"))
  14.             {
  15.                 return;
  16.             }
  17.             var sqLiteHelper = new SQLiteHelper();
  18.             var isMultipleTab = sqLiteHelper.GetSysBool(SysConst.Sys_IsMultipleTab);
  19.             if (!isMultipleTab)
  20.             {
  21.                 if (TabItemData.Any())
  22.                 {
  23.                     TabItemData.Clear();
  24.                 }
  25.                 CornerRadius = 10;
  26.                 MainW.Visibility = Visibility.Visible;
  27.                 MainTabW.Visibility = Visibility.Collapsed;
  28.                 MainW.ObjChangeRefreshEvent += Group_ChangeRefreshEvent;
  29.                 MainW.SelectedConnection = SelectendConnection;
  30.                 MainW.SelectedDataBase = selectDatabase;
  31.                 MainW.SelectedObject = objects;
  32.                 MainW.LoadPage(TreeViewData);
  33.                 return;
  34.             }
  35.             CornerRadius = 0;
  36.             MainW.Visibility = Visibility.Collapsed;
  37.             MainTabW.Visibility = Visibility.Visible;
  38.             var curItem = TabItemData.FirstOrDefault(x => x.DisplayName == objects.DisplayName);
  39.             if (curItem != null)
  40.             {
  41.                 MainTabW.SelectedItem = curItem;
  42.                 return;
  43.             }
  44.             var dic = new Dictionary<string, string>
  45.             {
  46.                 {"Type", "pack://application:,,,/Resources/svg/category.svg"},
  47.                 {"Table", "pack://application:,,,/Resources/svg/table.svg"},
  48.                 {"View", "pack://application:,,,/Resources/svg/view.svg"},
  49.                 {"Proc", "pack://application:,,,/Resources/svg/proc.svg"}
  50.             };
  51.             var mainW = new MainW
  52.             {
  53.                 SelectedConnection = SelectendConnection,
  54.                 SelectedDataBase = selectDatabase,
  55.                 SelectedObject = objects,
  56.             };
  57.             mainW.LoadPage(TreeViewData);
  58.             var tabItem = new MainTabWModel
  59.             {
  60.                 DisplayName = objects.DisplayName,
  61.                 Icon = dic[objects.Type],
  62.                 MainW = mainW
  63.             };
  64.             TabItemData.Insert(0, tabItem);
  65.             MainTabW.SelectedItem = TabItemData.First();
  66.             #endregion
  67.         }
复制代码
上面代码就是通过用户控件的依赖属性将主界面的相关信息一层层往后面传递,这里暂时只贴主界面到中间界面的传递代码,想看详细传递的过程可以去我的开源项目中查看。
那么在用户控件中我们怎么实现加载具体的列表信息呢?其实我们在点击左边菜单的时候就去加载用户控件里面的初始化数据加载方法就行了,就像上面代码中的MainW.LoadPage(TreeViewData);,这个就是用户控件中加载页面初始数据的方法,在这个方法里面我们实现列表页面的DataGrid数据绑定,下面是相关代码:
  1.         /// <summary>
  2.         /// 加载页面数据
  3.         /// </summary>
  4.         public void LoadPageData()
  5.         {
  6.             ChkAll.IsChecked = false;
  7.             NoDataText.Visibility = Visibility.Collapsed;
  8.             if (SelectedObject.Type == ObjType.Type)
  9.             {
  10.                 var headerT = "表名称";
  11.                 var placeHolderT = "请输入表名称或备注说明";
  12.                 switch (SelectedObject.Name)
  13.                 {
  14.                     case "treeTable": break;
  15.                     case "treeView":
  16.                         headerT = "视图名称";
  17.                         placeHolderT = "请输入视图名称或备注说明"; break;
  18.                     default:
  19.                         headerT = "存储过程名称";
  20.                         placeHolderT = "请输入存储过程名称或备注说明"; break;
  21.                 }
  22.                 ObjHead.Header = headerT;
  23.                 Placeholder = placeHolderT;
  24.                 if (SelectedObject.Parent == null)
  25.                 {
  26.                     ObjectsViewData = ObjectsViewData.First(x => x.Name == SelectedObject.Name).Children;
  27.                 }
  28.                 else
  29.                 {
  30.                     ObjectsViewData = ObjectsViewData.First(x => x.DisplayName == SelectedObject.Parent.DisplayName)
  31.                         .Children;
  32.                     ObjectsViewData = ObjectsViewData.First(x => x.Name == SelectedObject.Name).Children;
  33.                 }
  34.                 if (!ObjectsViewData.Any())
  35.                 {
  36.                     NoDataText.Visibility = Visibility.Visible;
  37.                 }
  38.                 ObjectsViewData.ForEach(x =>
  39.                 {
  40.                     x.IsChecked = false;
  41.                 });
  42.                 ObjItems = ObjectsViewData;
  43.                 SearchObject.Text = string.Empty;
  44.             }
  45.         }
复制代码
在这里我们的DataGrid就是用的MVVM模式实现的数据双向绑定,要实现这个绑定我们还要在页面的默认构造函数中写上一句代码:
  1.         public MainObjects()
  2.         {
  3.             InitializeComponent();
  4.             DataContext = this;
  5.         }
复制代码
这样就实现了DataGrid的数据绑定了。
好了,今天就分享到这了,想了解更多关于WPF相关的知识就请移步我的开源项目中查看吧。
开源地址

https://gitee.com/dotnetchina/SmartSQL
声明:SmartSQL已于2022.08.01正式加入Gitee开源组织dotNET China,为.net开源尽自己的绵薄之力,感谢各位的支持!


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4