农民 发表于 2022-9-4 16:50:56

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

项目背景

公司业务历史悠久且复杂,数据库的表更是多而繁杂,每次基于老业务做功能开发都需要去翻以前的表和业务代码。需要理解旧的表的用途以及包含的字段的含义,表少还好说,但是表一多这就很浪费时间,而且留下来的文档都是残缺不全,每次查一些表的含义都要捯饬很久。在网上搜索关于数据库文档管理工具搜到最多的就是Screw和DBCHM,一个是基于Java的工具、另一个则是bug很多,表一多就一直转圈圈进不去。所以自己就动手开发了这款SmartSQL的工具。
https://img2022.cnblogs.com/blog/627089/202207/627089-20220731162025265-1116344830.png
它是一款基于.Net 4.6.1、WPF开发的一款数据库文档管理,不仅支持多种数据库(SQLServer、MySQL、PostgreSQL、SQLite)表、视图、存储过程的查询管理,还支持对其进行导出成离线文档,支持的文档包括CHM、Word、Excel、PDF、HTML、Xml、Json、MarkDown等多种格式。
现在将它开源分享出来,供更多的小伙伴使用和参考学习(文末附开源地址)。
技术栈


[*].Net 4.6.1
[*]WPF
[*]HandyControl
[*]SqlSugar
[*]AvalonEdit
[*]SharpVectors
HandyControl是一款非常优秀的WPF框架,做出来的页面都很漂亮,所以我们选择使用它。
Nuget中引用HandyControl:
https://img2022.cnblogs.com/blog/627089/202207/627089-20220731160825057-268841996.png
一.菜单栏

https://img2022.cnblogs.com/blog/627089/202207/627089-20220731162248818-1700510450.png
然后我们要实现一个基于WPF边框上的菜单栏,刚好HandyControl中有这么一个菜单栏的控件,
下面就是实现菜单栏的方法:
`
<hc:GlowWindow.NonClientAreaContent>
    <StackPanel Height="29" Margin="25,0,0,0">
      <Menu HorizontalAlignment="Left">
            <MenuItem
                x:Name="SwitchMenu"
                Cursor="Hand"
                FontWeight="Bold"
                Foreground="{DynamicResource DarkPrimaryBrush}"
                Header="选择连接">
                <MenuItem.Icon>
                  <Path
                        Data="{StaticResource DownGeometry}"
                        Fill="{DynamicResource DarkPrimaryBrush}"
                        Stretch="Uniform" />
                </MenuItem.Icon>
                <MenuItem.ItemTemplate>
                  <HierarchicalDataTemplate>
                        <MenuItem
                            Width="160"
                            Margin="0"
                            Padding="0"
                            HorizontalAlignment="Left"
                            VerticalAlignment="Stretch"
                            Click="SwitchMenu_Click"
                            Cursor="Hand"
                            FontWeight="Normal"
                            Header="{Binding ConnectName}">
                            <MenuItem.Icon>
                              <svgc:SvgViewbox
                                    Width="16"
                                    Height="16"
                                    HorizontalAlignment="Left"
                                    IsHitTestVisible="False"
                                    Source="{Binding Icon}" />
                            </MenuItem.Icon>
                        </MenuItem>
                  </HierarchicalDataTemplate>
                </MenuItem.ItemTemplate>
            </MenuItem>
            <MenuItem
                Name="MenuConnect"
                Cursor="Hand"
                FontWeight="Bold"
                Foreground="{DynamicResource DarkPrimaryBrush}"
                Header="文件">
                <MenuItem.Icon>
                  <Path
                        Data="{StaticResource FileGeometry}"
                        Fill="{DynamicResource DarkPrimaryBrush}"
                        Stretch="Uniform" />
                </MenuItem.Icon>
                <MenuItem
                  Name="AddConnect"
                  Click="AddConnect_OnClick"
                  FontWeight="Normal"
                  Header="新建连接">
                  <MenuItem.Icon>
                        <Path
                            Data="{StaticResource NewConnectGeometry}"
                            Fill="{DynamicResource DarkPrimaryBrush}"
                            Stretch="Uniform" />
                  </MenuItem.Icon>
                </MenuItem>
                <MenuItem
                  Name="ImportMark"
                  Click="ImportMark_OnClick"
                  FontWeight="Normal"
                  Header="导入备注">
                  <MenuItem.Icon>
                        <Path
                            Data="{StaticResource ImportGeometry}"
                            Fill="{DynamicResource DarkPrimaryBrush}"
                            Stretch="Uniform" />
                  </MenuItem.Icon>
                </MenuItem>
                <MenuItem
                  Name="ExportDoc"
                  Click="ExportDoc_OnClick"
                  FontWeight="Normal"
                  Header="导出文档">
                  <MenuItem.Icon>
                        <Path
                            Data="{StaticResource ExportGeometry}"
                            Fill="{DynamicResource DarkPrimaryBrush}"
                            Stretch="Uniform" />
                  </MenuItem.Icon>
                </MenuItem>
            </MenuItem>
            <MenuItem
                Name="MenuGroup"
                Click="MenuGroup_OnClick"
                Cursor="Hand"
                FontWeight="Bold"
                Foreground="{DynamicResource DarkPrimaryBrush}"
                Header="分组">
                <MenuItem.Icon>
                  <Path
                        Data="{StaticResource GroupGeometry}"
                        Fill="{DynamicResource DarkPrimaryBrush}"
                        Stretch="Uniform" />
                </MenuItem.Icon>
            </MenuItem>
            <MenuItem
                Name="MenuSetting"
                Click="MenuSetting_OnClick"
                Cursor="Hand"
                FontWeight="Bold"
                Foreground="{DynamicResource DarkPrimaryBrush}"
                Header="设置">
                <MenuItem.Icon>
                  <Path
                        Data="{StaticResource SettingGeometry}"
                        Fill="{DynamicResource DarkPrimaryBrush}"
                        Stretch="Uniform" />
                </MenuItem.Icon>
            </MenuItem>
            <MenuItem
                Name="MenuAbout"
                Click="MenuAbout_OnClick"
                Cursor="Hand"
                FontWeight="Bold"
                Foreground="{DynamicResource DarkPrimaryBrush}"
                Header="关于">
                <MenuItem.Icon>
                  <Path
                        Data="{StaticResource InfoGeometry}"
                        Fill="{DynamicResource DarkPrimaryBrush}"
                        Stretch="Uniform" />
                </MenuItem.Icon>
            </MenuItem>
      </Menu>
    </StackPanel>
</hc:GlowWindow.NonClientAreaContent>其中有个小插曲,在WPF中是默认不支持svg图形的,所以我们需要引用一个组件:SharpVectors,它的使用方法是这样的,引用svg界面需要引入下面语句:
xmlns:svgc="http://sharpvectors.codeplex.com/svgc/"
然后引用要显示的svg图形:
二.左侧菜单栏

然后就是左侧的菜单栏,我们要实现一个数据库的选择和数据库对象的搜索,可以搜索相关表、视图、存储过程等对象。
首先我们要对我们的主界面进行一个简单的1:1:1的竖向布局,分别为左侧菜单栏、中间可以移动的分隔栏、右面的主界面:
   
    <Grid x:Name="GridMain" Background="{StaticResource CloudDrawingBrush}">
      <Grid.RowDefinitions>
            <RowDefinition Height="*" />
      </Grid.RowDefinitions>
      <Grid.ColumnDefinitions>
            <ColumnDefinition Width="3.3*" MinWidth="200" />
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="6.6*" />
      </Grid.ColumnDefinitions>
</Grid>现在我们要实现一个左侧树形的菜单栏,我们使用的是WPF里面的TreeView控件进行实现这样一个功能,下面是相关代码:
<hc:GlowWindow.NonClientAreaContent>
    <StackPanel Height="29" Margin="25,0,0,0">
      <Menu HorizontalAlignment="Left">
            <MenuItem
                x:Name="SwitchMenu"
                Cursor="Hand"
                FontWeight="Bold"
                Foreground="{DynamicResource DarkPrimaryBrush}"
                Header="选择连接">
                <MenuItem.Icon>
                  <Path
                        Data="{StaticResource DownGeometry}"
                        Fill="{DynamicResource DarkPrimaryBrush}"
                        Stretch="Uniform" />
                </MenuItem.Icon>
                <MenuItem.ItemTemplate>
                  <HierarchicalDataTemplate>
                        <MenuItem
                            Width="160"
                            Margin="0"
                            Padding="0"
                            HorizontalAlignment="Left"
                            VerticalAlignment="Stretch"
                            Click="SwitchMenu_Click"
                            Cursor="Hand"
                            FontWeight="Normal"
                            Header="{Binding ConnectName}">
                            <MenuItem.Icon>
                              <svgc:SvgViewbox
                                    Width="16"
                                    Height="16"
                                    HorizontalAlignment="Left"
                                    IsHitTestVisible="False"
                                    Source="{Binding Icon}" />
                            </MenuItem.Icon>
                        </MenuItem>
                  </HierarchicalDataTemplate>
                </MenuItem.ItemTemplate>
            </MenuItem>
            <MenuItem
                Name="MenuConnect"
                Cursor="Hand"
                FontWeight="Bold"
                Foreground="{DynamicResource DarkPrimaryBrush}"
                Header="文件">
                <MenuItem.Icon>
                  <Path
                        Data="{StaticResource FileGeometry}"
                        Fill="{DynamicResource DarkPrimaryBrush}"
                        Stretch="Uniform" />
                </MenuItem.Icon>
                <MenuItem
                  Name="AddConnect"
                  Click="AddConnect_OnClick"
                  FontWeight="Normal"
                  Header="新建连接">
                  <MenuItem.Icon>
                        <Path
                            Data="{StaticResource NewConnectGeometry}"
                            Fill="{DynamicResource DarkPrimaryBrush}"
                            Stretch="Uniform" />
                  </MenuItem.Icon>
                </MenuItem>
                <MenuItem
                  Name="ImportMark"
                  Click="ImportMark_OnClick"
                  FontWeight="Normal"
                  Header="导入备注">
                  <MenuItem.Icon>
                        <Path
                            Data="{StaticResource ImportGeometry}"
                            Fill="{DynamicResource DarkPrimaryBrush}"
                            Stretch="Uniform" />
                  </MenuItem.Icon>
                </MenuItem>
                <MenuItem
                  Name="ExportDoc"
                  Click="ExportDoc_OnClick"
                  FontWeight="Normal"
                  Header="导出文档">
                  <MenuItem.Icon>
                        <Path
                            Data="{StaticResource ExportGeometry}"
                            Fill="{DynamicResource DarkPrimaryBrush}"
                            Stretch="Uniform" />
                  </MenuItem.Icon>
                </MenuItem>
            </MenuItem>
            <MenuItem
                Name="MenuGroup"
                Click="MenuGroup_OnClick"
                Cursor="Hand"
                FontWeight="Bold"
                Foreground="{DynamicResource DarkPrimaryBrush}"
                Header="分组">
                <MenuItem.Icon>
                  <Path
                        Data="{StaticResource GroupGeometry}"
                        Fill="{DynamicResource DarkPrimaryBrush}"
                        Stretch="Uniform" />
                </MenuItem.Icon>
            </MenuItem>
            <MenuItem
                Name="MenuSetting"
                Click="MenuSetting_OnClick"
                Cursor="Hand"
                FontWeight="Bold"
                Foreground="{DynamicResource DarkPrimaryBrush}"
                Header="设置">
                <MenuItem.Icon>
                  <Path
                        Data="{StaticResource SettingGeometry}"
                        Fill="{DynamicResource DarkPrimaryBrush}"
                        Stretch="Uniform" />
                </MenuItem.Icon>
            </MenuItem>
            <MenuItem
                Name="MenuAbout"
                Click="MenuAbout_OnClick"
                Cursor="Hand"
                FontWeight="Bold"
                Foreground="{DynamicResource DarkPrimaryBrush}"
                Header="关于">
                <MenuItem.Icon>
                  <Path
                        Data="{StaticResource InfoGeometry}"
                        Fill="{DynamicResource DarkPrimaryBrush}"
                        Stretch="Uniform" />
                </MenuItem.Icon>
            </MenuItem>
      </Menu>
    </StackPanel>
</hc:GlowWindow.NonClientAreaContent><hc:GlowWindow.NonClientAreaContent>
    <StackPanel Height="29" Margin="25,0,0,0">
      <Menu HorizontalAlignment="Left">
            <MenuItem
                x:Name="SwitchMenu"
                Cursor="Hand"
                FontWeight="Bold"
                Foreground="{DynamicResource DarkPrimaryBrush}"
                Header="选择连接">
                <MenuItem.Icon>
                  <Path
                        Data="{StaticResource DownGeometry}"
                        Fill="{DynamicResource DarkPrimaryBrush}"
                        Stretch="Uniform" />
                </MenuItem.Icon>
                <MenuItem.ItemTemplate>
                  <HierarchicalDataTemplate>
                        <MenuItem
                            Width="160"
                            Margin="0"
                            Padding="0"
                            HorizontalAlignment="Left"
                            VerticalAlignment="Stretch"
                            Click="SwitchMenu_Click"
                            Cursor="Hand"
                            FontWeight="Normal"
                            Header="{Binding ConnectName}">
                            <MenuItem.Icon>
                              <svgc:SvgViewbox
                                    Width="16"
                                    Height="16"
                                    HorizontalAlignment="Left"
                                    IsHitTestVisible="False"
                                    Source="{Binding Icon}" />
                            </MenuItem.Icon>
                        </MenuItem>
                  </HierarchicalDataTemplate>
                </MenuItem.ItemTemplate>
            </MenuItem>
            <MenuItem
                Name="MenuConnect"
                Cursor="Hand"
                FontWeight="Bold"
                Foreground="{DynamicResource DarkPrimaryBrush}"
                Header="文件">
                <MenuItem.Icon>
                  <Path
                        Data="{StaticResource FileGeometry}"
                        Fill="{DynamicResource DarkPrimaryBrush}"
                        Stretch="Uniform" />
                </MenuItem.Icon>
                <MenuItem
                  Name="AddConnect"
                  Click="AddConnect_OnClick"
                  FontWeight="Normal"
                  Header="新建连接">
                  <MenuItem.Icon>
                        <Path
                            Data="{StaticResource NewConnectGeometry}"
                            Fill="{DynamicResource DarkPrimaryBrush}"
                            Stretch="Uniform" />
                  </MenuItem.Icon>
                </MenuItem>
                <MenuItem
                  Name="ImportMark"
                  Click="ImportMark_OnClick"
                  FontWeight="Normal"
                  Header="导入备注">
                  <MenuItem.Icon>
                        <Path
                            Data="{StaticResource ImportGeometry}"
                            Fill="{DynamicResource DarkPrimaryBrush}"
                            Stretch="Uniform" />
                  </MenuItem.Icon>
                </MenuItem>
                <MenuItem
                  Name="ExportDoc"
                  Click="ExportDoc_OnClick"
                  FontWeight="Normal"
                  Header="导出文档">
                  <MenuItem.Icon>
                        <Path
                            Data="{StaticResource ExportGeometry}"
                            Fill="{DynamicResource DarkPrimaryBrush}"
                            Stretch="Uniform" />
                  </MenuItem.Icon>
                </MenuItem>
            </MenuItem>
            <MenuItem
                Name="MenuGroup"
                Click="MenuGroup_OnClick"
                Cursor="Hand"
                FontWeight="Bold"
                Foreground="{DynamicResource DarkPrimaryBrush}"
                Header="分组">
                <MenuItem.Icon>
                  <Path
                        Data="{StaticResource GroupGeometry}"
                        Fill="{DynamicResource DarkPrimaryBrush}"
                        Stretch="Uniform" />
                </MenuItem.Icon>
            </MenuItem>
            <MenuItem
                Name="MenuSetting"
                Click="MenuSetting_OnClick"
                Cursor="Hand"
                FontWeight="Bold"
                Foreground="{DynamicResource DarkPrimaryBrush}"
                Header="设置">
                <MenuItem.Icon>
                  <Path
                        Data="{StaticResource SettingGeometry}"
                        Fill="{DynamicResource DarkPrimaryBrush}"
                        Stretch="Uniform" />
                </MenuItem.Icon>
            </MenuItem>
            <MenuItem
                Name="MenuAbout"
                Click="MenuAbout_OnClick"
                Cursor="Hand"
                FontWeight="Bold"
                Foreground="{DynamicResource DarkPrimaryBrush}"
                Header="关于">
                <MenuItem.Icon>
                  <Path
                        Data="{StaticResource InfoGeometry}"
                        Fill="{DynamicResource DarkPrimaryBrush}"
                        Stretch="Uniform" />
                </MenuItem.Icon>
            </MenuItem>
      </Menu>
    </StackPanel>
</hc:GlowWindow.NonClientAreaContent>   
    <Grid x:Name="GridMain" Background="{StaticResource CloudDrawingBrush}">
      <Grid.RowDefinitions>
            <RowDefinition Height="*" />
      </Grid.RowDefinitions>
      <Grid.ColumnDefinitions>
            <ColumnDefinition Width="3.3*" MinWidth="200" />
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="6.6*" />
      </Grid.ColumnDefinitions>
</Grid>   
    <Grid x:Name="GridMain" Background="{StaticResource CloudDrawingBrush}">
      <Grid.RowDefinitions>
            <RowDefinition Height="*" />
      </Grid.RowDefinitions>
      <Grid.ColumnDefinitions>
            <ColumnDefinition Width="3.3*" MinWidth="200" />
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="6.6*" />
      </Grid.ColumnDefinitions>
</Grid>   
    <Grid x:Name="GridMain" Background="{StaticResource CloudDrawingBrush}">
      <Grid.RowDefinitions>
            <RowDefinition Height="*" />
      </Grid.RowDefinitions>
      <Grid.ColumnDefinitions>
            <ColumnDefinition Width="3.3*" MinWidth="200" />
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="6.6*" />
      </Grid.ColumnDefinitions>
</Grid>   
    <Grid x:Name="GridMain" Background="{StaticResource CloudDrawingBrush}">
      <Grid.RowDefinitions>
            <RowDefinition Height="*" />
      </Grid.RowDefinitions>
      <Grid.ColumnDefinitions>
            <ColumnDefinition Width="3.3*" MinWidth="200" />
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="6.6*" />
      </Grid.ColumnDefinitions>
</Grid>                                        在这里我没有详细介绍底层c#的相关代码,里面逻辑有些复杂感兴趣的可以去我的开源项目中学习。在上面的左侧菜单代码中,我们使用的不仅有TreeView控件、也有ContextMenu、hc:LoadingLine等控件,还有自己写的自定义控件。
其实WPF要比WinForm好用不少,不仅支持MVVM数据绑定还支持灵活的页面渲染,自从用了WPF再也不用WinForm了。
今天分享暂时到这里,下一篇讲介绍DataGrid表格数据绑定及相关条件搜索。下面是工具的开源地址,感兴趣的可以Clone下来学习一下。码砖不易,喜欢的麻烦点下Star.
开源地址

https://gitee.com/izhaofu/SmartSQL

https://img2022.cnblogs.com/blog/627089/202207/627089-20220731163845669-2112065971.png

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
页: [1]
查看完整版本: 基于WPF重复造轮子,写一款数据库文档管理工具(一)