wpf报表怎么做(基于WPF重复造轮子)

wpf报表怎么做(基于WPF重复造轮子)(1)

SmartSQL - 一款方便、快捷的数据库文档管理工具

项目背景

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

它是一款基于.Net 4.6.1、WPF开发的一款数据库文档管理,不仅支持多种数据库(SQLServer、MySQL、PostgreSQL、SQLite)表、视图、存储过程的查询管理,还支持对其进行导出成离线文档,支持的文档包括CHM、Word、Excel、PDF、HTML、Xml、Json、MarkDown等多种格式。

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

wpf报表怎么做(基于WPF重复造轮子)(2)

技术栈
  • .Net 4.6.1
  • WPF
  • HandyControl
  • SqlSugar
  • AvalonEdit
  • SharpVectors

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

wpf报表怎么做(基于WPF重复造轮子)(3)

引用HandyControl

一.菜单栏

wpf报表怎么做(基于WPF重复造轮子)(4)

菜单栏

然后我们要实现一个基于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" Style="{StaticResource ComboBoxExtend}" 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" Style="{StaticResource SearchBarPlus}" TextChanged="SearchMenu_OnTextChanged" /> <TabControl x:Name="TabLeftType" Margin="0,65,0,40" SelectionChanged="TabLeftType_OnSelectionChanged" Style="{StaticResource TabControlInLine}"> <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" Style="{StaticResource ComboBoxExtend}" /> </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" Style="{StaticResource ComboBoxExtend}" /> </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控件、也有ContextMenu、hc:LoadingLine等控件,还有自己写的自定义控件。

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

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

开源地址

SmartSQL: 一款方便、快捷的数据库文档查询、生成工具,支持SqlServer/MySql/PostgreSQL/SQLite数据库表结构文档查询、生成;导出文档支持CHM、Word、Excel、PDF、Html、Xml、Json、MarkDown等多种格式。

wpf报表怎么做(基于WPF重复造轮子)(5)

,

免责声明:本文仅代表文章作者的个人观点,与本站无关。其原创性、真实性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容文字的真实性、完整性和原创性本站不作任何保证或承诺,请读者仅作参考,并自行核实相关内容。文章投诉邮箱:anhduc.ph@yahoo.com

    分享
    投诉
    首页