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

博客 分享
0 99
优雅殿下
优雅殿下 2022-07-31 17:02:29
悬赏:0 积分 收藏

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

基于WPF重复造轮子,写一款数据库文档管理工具(一) 公司业务历史悠久且复杂,数据库的表更是多而繁杂,每次基于老业务做功能开发都需要去翻以前的表和业务代码。需要理解旧的表的用途以及包含的字段的含义,表少还好说,但是表一多这就很浪费时间,而且留下来的文档都是残缺不全,每次查一些表的含义都要捯饬很久。在网上搜索关于数据库文档管理工具搜到最多的就是Screw和DBCHM,一个是基于Java的工具、另一个则是bug很多,表一多就一直转圈圈进不去。所以自己就动手开发了这款SmartSQL的工具。

项目背景

公司业务历史悠久且复杂,数据库的表更是多而繁杂,每次基于老业务做功能开发都需要去翻以前的表和业务代码。需要理解旧的表的用途以及包含的字段的含义,表少还好说,但是表一多这就很浪费时间,而且留下来的文档都是残缺不全,每次查一些表的含义都要捯饬很久。在网上搜索关于数据库文档管理工具搜到最多的就是Screw和DBCHM,一个是基于Java的工具、另一个则是bug很多,表一多就一直转圈圈进不去。所以自己就动手开发了这款SmartSQL的工具。

它是一款基于.Net 4.6.1WPF开发的一款数据库文档管理,不仅支持多种数据库(SQLServerMySQLPostgreSQLSQLite)表、视图、存储过程的查询管理,还支持对其进行导出成离线文档,支持的文档包括CHMWordExcelPDFHTMLXmlJsonMarkDown等多种格式。

现在将它开源分享出来,供更多的小伙伴使用和参考学习(文末附开源地址)。

技术栈

  • .Net 4.6.1
  • WPF
  • HandyControl
  • SqlSugar
  • AvalonEdit
  • SharpVectors

HandyControl是一款非常优秀的WPF框架,做出来的页面都很漂亮,所以我们选择使用它。
Nuget中引用HandyControl

一.菜单栏

然后我们要实现一个基于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图形:

<svgc:SvgViewbox          Width="16"          Height="16"          HorizontalAlignment="Left"          IsHitTestVisible="False"          Source="{Binding Icon}" />

二.左侧菜单栏

然后就是左侧的菜单栏,我们要实现一个数据库的选择和数据库对象的搜索,可以搜索相关表、视图、存储过程等对象。
首先我们要对我们的主界面进行一个简单的1:1:1的竖向布局,分别为左侧菜单栏、中间可以移动的分隔栏、右面的主界面:

    <!--  Main区域  -->    <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控件进行实现这样一个功能,下面是相关代码:

        <DockPanel Grid.Row="0" Grid.Column="0">            <hc:SimplePanel>                <Border                    Margin="5,5,0,5"                    Background="{DynamicResource RegionBrush}"                    CornerRadius="{Binding CornerRadius}">                    <Grid                        Height="Auto"                        Margin="5"                        Background="Transparent">                        <TextBox x:Name="HidSelectDatabase" Visibility="Hidden" />                        <Grid>                            <Grid.ColumnDefinitions>                                <ColumnDefinition Width="8*" />                                <ColumnDefinition Width="1*" MinWidth="30" />                            </Grid.ColumnDefinitions>                            <ComboBox                                x:Name="SelectDatabase"                                Height="30"                                VerticalAlignment="Top"                                HorizontalContentAlignment="Stretch"                                hc:BorderElement.CornerRadius="5"                                hc:InfoElement.Placeholder="请选择数据库"                                Cursor="Hand"                                IsTextSearchEnabled="True"                                SelectionChanged="SelectDatabase_OnSelectionChanged"                                                                Text="{Binding DbName}">                                <ComboBox.ItemTemplate>                                    <DataTemplate>                                        <StackPanel VerticalAlignment="Center" Orientation="Horizontal">                                            <Image                                                Width="11"                                                Height="15"                                                Source="/SmartSQL;component/Resources/Img/dataBase.ico" />                                            <TextBlock                                                Margin="5,0,0,0"                                                HorizontalAlignment="Center"                                                VerticalAlignment="Center"                                                Text="{Binding DbName}" />                                        </StackPanel>                                    </DataTemplate>                                </ComboBox.ItemTemplate>                            </ComboBox>                            <Button                                Name="BtnFresh"                                Grid.Column="2"                                Margin="0,0,0,0"                                Padding="4"                                VerticalAlignment="Top"                                Background="Transparent"                                BorderThickness="0"                                Click="BtnFresh_OnClick"                                Cursor="Hand">                                <Button.Content>                                    <Image Source="/SmartSQL;component/Resources/Img/Refresh.png" Stretch="Fill" />                                </Button.Content>                            </Button>                        </Grid>                        <hc:SearchBar                            x:Name="SearchMenu"                            Height="30"                            Margin="0,34,0,0"                            Padding="5,0,5,0"                            VerticalAlignment="Top"                            HorizontalContentAlignment="Stretch"                            hc:BorderElement.CornerRadius="5"                            hc:InfoElement.Placeholder="搜索数据表/视图/存储过程"                            FontSize="13"                            ShowClearButton="True"                                                        TextChanged="SearchMenu_OnTextChanged" />                        <TabControl                            x:Name="TabLeftType"                            Margin="0,65,0,40"                            SelectionChanged="TabLeftType_OnSelectionChanged"                            >                            <TabItem                                x:Name="TabAllData"                                Cursor="Hand"                                Header="全部"                                IsSelected="True" />                            <TabItem                                x:Name="TabGroupData"                                Cursor="Hand"                                Header="分组"                                IsSelected="False" />                            <!--<TabItem                                x:Name="TabFavData"                                Cursor="Hand"                                Header="收藏"                                IsSelected="False" />-->                        </TabControl>                        <TreeView                            x:Name="TreeViewTables"                            Margin="0,100,0,0"                            VerticalAlignment="Top"                            BorderThickness="0"                            ItemsSource="{Binding TreeViewData}"                            SelectedItemChanged="SelectedTable_OnClick">                            <TreeView.ItemContainerStyle>                                <Style BasedOn="{StaticResource TreeViewItemBaseStyle}" TargetType="{x:Type TreeViewItem}">                                    <Setter Property="IsExpanded" Value="{Binding IsExpanded}" />                                    <Setter Property="FontWeight" Value="{Binding FontWeight}" />                                    <Setter Property="FontSize" Value="12" />                                    <Setter Property="Visibility" Value="{Binding Visibility}" />                                    <Setter Property="Foreground" Value="{Binding TextColor}" />                                    <Setter Property="Cursor" Value="Hand" />                                    <!--  禁止水平滚动条自动滚动  -->                                    <EventSetter Event="RequestBringIntoView" Handler="EventSetter_OnHandler" />                                    <Style.Triggers>                                        <Trigger Property="IsSelected" Value="True">                                            <Setter Property="FontWeight" Value="Bold" />                                        </Trigger>                                    </Style.Triggers>                                </Style>                            </TreeView.ItemContainerStyle>                            <TreeView.ContextMenu>                                <!--  右键菜单  -->                                <ContextMenu Visibility="Visible">                                    <MenuItem                                        x:Name="MenuSelectedItem"                                        Padding="5,0,5,0"                                        VerticalAlignment="Center"                                        Click="MenuSelectedItem_OnClick"                                        Cursor="Hand"                                        Header="复制对象名" />                                </ContextMenu>                            </TreeView.ContextMenu>                            <TreeView.ItemTemplate>                                <HierarchicalDataTemplate DataType="{x:Type models:TreeNodeItem}" ItemsSource="{Binding Children}">                                    <StackPanel Orientation="Horizontal">                                        <svgc:SvgViewbox                                            Width="12"                                            Height="12"                                            Margin="0,0,5,0"                                            HorizontalAlignment="Left"                                            Source="{Binding Icon}" />                                        <TextBlock                                            VerticalAlignment="Center"                                            FontSize="12"                                            Text="{Binding DisplayName}"                                            ToolTip="{Binding DisplayName}" />                                    </StackPanel>                                </HierarchicalDataTemplate>                            </TreeView.ItemTemplate>                        </TreeView>                        <Grid                            x:Name="NoDataText"                            Margin="0,100,0,5"                            HorizontalAlignment="Stretch"                            Background="White"                            Cursor="Arrow">                            <local:NoDataArea                                x:Name="NoDataAreaText"                                Margin="0"                                HorizontalAlignment="Center"                                ShowType="All" />                        </Grid>                        <Grid                            Margin="0"                            VerticalAlignment="Bottom"                            Visibility="Hidden">                            <Grid.ColumnDefinitions>                                <ColumnDefinition Width="4*" />                                <ColumnDefinition Width="6*" />                                <ColumnDefinition Width="Auto" />                            </Grid.ColumnDefinitions>                            <Grid>                                <ComboBox                                    x:Name="CbTargetConnect"                                    Height="26"                                    VerticalAlignment="Bottom"                                    HorizontalContentAlignment="Left"                                    hc:InfoElement.Placeholder="目标连接"                                    Cursor="Hand"                                    DisplayMemberPath="ConnectName"                                    IsTextSearchEnabled="True"                                    SelectedValuePath="DbMasterConnectString"                                    SelectionChanged="CbTargetConnect_OnSelectionChanged"                                     />                            </Grid>                            <Grid Grid.Column="1" Margin="5,0,0,0">                                <ComboBox                                    x:Name="CbTargetDatabase"                                    MinWidth="50"                                    VerticalAlignment="Bottom"                                    HorizontalContentAlignment="Left"                                    hc:InfoElement.Placeholder="目标数据库"                                    Cursor="Hand"                                    IsTextSearchEnabled="True"                                     />                            </Grid>                            <Grid Grid.Column="2">                                <!--  差异比较按钮  -->                                <Button                                    x:Name="BtnCompare"                                    Height="30"                                    Margin="5,5,0,0"                                    HorizontalAlignment="Right"                                    hc:BorderElement.CornerRadius="6"                                    hc:IconElement.Geometry="{StaticResource CompareGeometry}"                                    Click="BtnCompare_OnClick"                                    Content="差异比较"                                    Cursor="Hand" />                            </Grid>                        </Grid>                        <!--  数据加载Loading  -->                        <hc:LoadingLine                            x:Name="LoadingLine"                            Margin="0,0,0,0"                            Visibility="Collapsed" />                    </Grid>                </Border>            </hc:SimplePanel>        </DockPanel>

在这里我没有详细介绍底层c#的相关代码,里面逻辑有些复杂感兴趣的可以去我的开源项目中学习。在上面的左侧菜单代码中,我们使用的不仅有TreeView控件、也有ContextMenuhc:LoadingLine等控件,还有自己写的自定义控件。

其实WPF要比WinForm好用不少,不仅支持MVVM数据绑定还支持灵活的页面渲染,自从用了WPF再也不用WinForm了。

今天分享暂时到这里,下一篇讲介绍DataGrid表格数据绑定及相关条件搜索。下面是工具的开源地址,感兴趣的可以Clone下来学习一下。码砖不易,喜欢的麻烦点下Star.

开源地址

https://gitee.com/izhaofu/SmartSQL


posted @ 2022-07-31 16:44 月亮邮递员 阅读(6) 评论(0) 编辑 收藏 举报
回帖
    优雅殿下

    优雅殿下 (王者 段位)

    2017 积分 (2)粉丝 (47)源码

    小小码农,大大世界

     

    温馨提示

    亦奇源码

    最新会员