WinForm VB.NET 承载 WPF Ribbon
在 winforms VB.NET 项目中承载带有 Ribbon 的 WPF 用户控件
引言
本文和演示受到 C# WPF WYSIWYG HTML Editor - CodeProject 文章的启发,该文章展示了一个漂亮的 Ribbon UI,并给了我一些想法、代码片段和图像。
所以我的想法是在一个 winforms
VB.NET 项目中承载一个带有 Ribbon
的 WPF 用户控件
。
这只是一个带有示例菜单项和演示代码的演示,而不是富文本编辑器。
背景
我不想“克隆”上述文章中的 HTML 编辑器,并决定在 winform 上使用一个 richtextcontrol
,并创建一个带有菜单项和按钮的 WPF Ribbon
来控制它。
winform 上的结构很简单。
有一个 splitcontainer
, 带有 ElementHost
控件的 panel1
(在顶部)。
带有 tabcontrol
和 Richtextbox
es 的 Panel2
(在底部)。
Winform 概念和代码
一旦 WPF Usercontrol
可用,它就会出现在工具箱中。
当您将其从工具箱拖到 Splitcontainer Panel1
时,会放置一个 ElementHost
控件,该控件承载 usercontrol
。
代码显示我们在 winform
上使用变量 MyRibbonUserControl
以便轻松访问 WPF usercontrol
。
Public Class AppForm
Inherits Form
Private WithEvents MyRibbonUserControl As New UserControlRibbonWPF
Private blnIsMinimized As Boolean
Private Sub AppForm_Load(sender As Object, e As EventArgs) Handles Me.Load
Try
ElementHost1.Dock = DockStyle.Fill
MyRibbonUserControl = ElementHost1.Child
一些可能发生的错误会写入日志文件,我们将其用作 RTBox
的数据源。
在模块 Mod_Public
中,我们声明
Public WithEvents activeRichTextBox As RichTextBox
它在 winform
中用于
Private Sub RichTextBox_Enter(ByVal sender As System.Object,
ByVal e As System.EventArgs) Handles WinformRichTextBox.MouseClick,
WinformRichTextBox.Enter, WinformRichTextBox.MouseEnter,
WinformRichTextBox.TextChanged,
LogRichTextBox.MouseClick, LogRichTextBox.Enter,
LogRichTextBox.MouseEnter, LogRichTextBox.TextChanged
activeRichTextBox = CType(sender, RichTextBox)
End Sub
当应用程序显示时,我们也可以为 WPF Ribbon
执行一些配置 | 设置。
Private Sub AppForm_Shown(sender As Object, e As EventArgs) Handles Me.Shown
Try
activeRichTextBox = WinformRichTextBox
activeRichTextBox.Text = ReadTextLines("Log.txt")
' Configuration | Settings for WPF Ribbon
With MyRibbonUserControl
blnIsMinimized = .RibbonSizeIsMinimized
.TabHelp.IsEnabled = True
.RibbonWPF.Visibility = Windows.Visibility.Visible
winform 上的剩余代码主要与将在下面介绍的 Ribbon 设置有关。
WPF 用户控件概念和代码
Ribbon 包括
- 应用程序菜单
- QAT (
QuickAccessToolbar
) Ribbon
选项卡 “开始”,“Ribbon
设置”和“帮助”
应用程序菜单
QAT (QuickAccessToolbar)
您可以从 QAT 中删除按钮(右键单击时,会显示上下文菜单)。
您可以将 QAT 显示在 Ribbon
下方
您也可以从“设置”选项卡还原 QAT。
您可以更改 Ribbon 的 backcolor
。
Ribbon 选项卡 “开始”,“插入”,“Ribbon 设置”和“帮助”
可以通过上下文菜单或双击选项卡标题来最小化 Ribbon
。
UserControlRibbonWPF.xaml.vb 中的 VB.NET 代码
Public Sub New()
显示使用了 commandBinding
,我 在 这里 找到的。
Public Sub New()
Dim binding As CommandBinding
binding = New CommandBinding(ApplicationCommands.[New])
AddHandler binding.Executed, AddressOf New_Click
Me.CommandBindings.Add(binding)
binding = New CommandBinding(ApplicationCommands.Open)
AddHandler binding.Executed, AddressOf Open_Click
Me.CommandBindings.Add(binding)
binding = New CommandBinding(ApplicationCommands.Close)
AddHandler binding.Executed, AddressOf CloseCommand
Me.CommandBindings.Add(binding)
binding = New CommandBinding(ApplicationCommands.Print)
AddHandler binding.Executed, AddressOf PrintCommand
Me.CommandBindings.Add(binding)
binding = New CommandBinding(ApplicationCommands.SaveAs)
AddHandler binding.Executed, AddressOf SaveAs_Click
Me.CommandBindings.Add(binding)
End Sub
WPF 端其他 button
事件的代码几乎与 winform 端相同。
对于处理 RTBox
内容,可以使用上述变量 activeRichTextBox
。
示例
Private Sub LeftAlignRibbonButton_Click(sender As Object, e As Windows.RoutedEventArgs) _
Handles LeftAlignRibbonButton.Click
If activeRichTextBox IsNot Nothing Then If activeRichTextBox.SelectedText.Length = 0 _
Then Exit Sub
If activeRichTextBox IsNot Nothing Then activeRichTextBox.SelectionAlignment = _
System.Windows.Forms.HorizontalAlignment.Left
End Sub
XAML 文件 UserControlRibbonWPF.xaml
应用程序菜单部分
<Ribbon.ApplicationMenu>
<RibbonApplicationMenu CanAddToQuickAccessToolBarDirectly="True">
<RibbonApplicationMenuItem x:Name="AppCmdNew" Header="New"
Command="ApplicationCommands.New" IsCheckable="False"
ImageSource="Images/newdocument32.png"
QuickAccessToolBarImageSource="Images/newdocument32.png"
CanAddToQuickAccessToolBarDirectly="False" />
<RibbonApplicationMenuItem x:Name="AppCmdOpen" Header="Open"
Command="ApplicationCommands.Open" IsCheckable="False"
ImageSource="Images/open16.png"
QuickAccessToolBarImageSource="Images/open16.png"
CanAddToQuickAccessToolBarDirectly="False" />
<RibbonApplicationMenuItem x:Name="AppCmdSaveAs"
Header="Save As" Command="ApplicationCommands.SaveAs"
IsCheckable="False" ImageSource="Images/save16.png"
QuickAccessToolBarImageSource="Images/save16.png"
CanAddToQuickAccessToolBarDirectly="False" />
<RibbonApplicationMenuItem x:Name="AppCmdPrint" Header="Print"
Command="ApplicationCommands.Print" IsCheckable="False"
ImageSource="Images/print.png"
QuickAccessToolBarImageSource="Images/print.png"
CanAddToQuickAccessToolBarDirectly="False" />
<RibbonApplicationMenuItem x:Name="AppCmdClose"
Header="Close App" Command="ApplicationCommands.Close"
ImageSource="Images/close.png"
QuickAccessToolBarImageSource="Images/close.png"
CanAddToQuickAccessToolBarDirectly="False" />
</RibbonApplicationMenu>
</Ribbon.ApplicationMenu>
QAT 部分
<Ribbon.QuickAccessToolBar>
<RibbonQuickAccessToolBar HorizontalAlignment="Right" Width="120">
<RibbonButton x:Name="AppCmdNewQAT" Command="ApplicationCommands.New"
SmallImageSource="Images\newdocument32.png" KeyTip="N" />
<RibbonButton x:Name="AppCmdOpenQAT" Command="ApplicationCommands.Open"
SmallImageSource="Images\open16.png" KeyTip="O"/>
<RibbonButton x:Name="AppCmdSaveAsQAT" Command="ApplicationCommands.SaveAs"
SmallImageSource="Images\save16.png" KeyTip="S"/>
<RibbonButton x:Name="AppCmdCloseQAT" Command="ApplicationCommands.Close"
SmallImageSource="Images\close.png"/>
</RibbonQuickAccessToolBar>
</Ribbon.QuickAccessToolBar>
以及 EditorTab
的第一部分 ("Start
")
<RibbonTab x:Name="EditorTab" Header="Start" Height="97" Margin="0,0,-2,-9"
RenderTransformOrigin="0.5,0.682" KeyTip="E">
<RibbonGroup Header="File" Height="92" Margin="0"
VerticalAlignment="Top" Width="199" FontFamily="Arial"
CanAddToQuickAccessToolBarDirectly="False">
<RibbonButton x:Name="New" Content="RibbonButton"
HorizontalAlignment="Left" Height="53" Margin="10,2,-86,-53"
VerticalAlignment="Top" Width="80" Label="New"
LargeImageSource="Images/newdocument32.png" ToolTipTitle=""
ToolTip="New" KeyTip="N" CanAddToQuickAccessToolBarDirectly="False" />
<RibbonButton x:Name="Open" Content="RibbonButton"
HorizontalAlignment="Left" Height="22" Margin="95,0,-176,-26"
VerticalAlignment="Top" Width="85" Label=" Open"
SmallImageSource="Images/open16.png" ToolTipTitle=""
ToolTip="Open" KeyTip="O" CanAddToQuickAccessToolBarDirectly="False" />
<RibbonButton x:Name="SaveAs" Content="RibbonButton"
HorizontalAlignment="Left" Height="Auto" Margin="94,24,-162,-70"
VerticalAlignment="Top" Width="80" Label=" Save As" KeyTip="S"
AutomationProperties.AccessKey="S" AutomationProperties.AcceleratorKey="S"
SmallImageSource="Images/save16.png"
CanAddToQuickAccessToolBarDirectly="False"/>
<RibbonButton x:Name="Save" Content="RibbonButton"
HorizontalAlignment="Left" Height="Auto" Margin="94,46,-162,-70"
VerticalAlignment="Top" Width="80" Label=" Save" KeyTip="S"
AutomationProperties.AccessKey="S" AutomationProperties.AcceleratorKey="S"
SmallImageSource="Images/save16.png" Visibility="Hidden"
CanAddToQuickAccessToolBarDirectly="False"/>
</RibbonGroup>
<RibbonGroup Header="Clipboard" Margin="0" Width="100" FontFamily="Arial"
VerticalAlignment="Top" Height="92" CanAddToQuickAccessToolBarDirectly="False">
<RibbonButton x:Name="ClipboardCmdCut" Label=" Cut"
SmallImageSource="Images/cut16.png" Margin="0,2,0,0"
CanAddToQuickAccessToolBarDirectly="False"/>
<RibbonButton x:Name="ClipboardCmdCopy" Label=" Copy"
SmallImageSource="Images/copy16.png" KeyTip="C" Margin="0,2,-1.708,0"
Height="Auto" CanAddToQuickAccessToolBarDirectly="False"/>
<RibbonButton x:Name="ClipboardCmdPaste" Label=" Paste"
SmallImageSource="Images/paste16.png" Margin="0,2,0,0"
CanAddToQuickAccessToolBarDirectly="False"/>
</RibbonGroup>
关闭应用程序时保存 QAT 状态
AppForm.vb 中的 VB.NET 代码
Private Sub AppForm_Closing(sender As Object, e As CancelEventArgs) Handles Me.Closing
Try
If MyRibbonUserControl.AppCmdNewQAT.IsLoaded = False Then
My.Settings.AppCmdNewQAT_Visible = False
ElseIf MyRibbonUserControl.AppCmdNewQAT.IsLoaded = True Then
My.Settings.AppCmdNewQAT_Visible = True
End If
If MyRibbonUserControl.AppCmdOpenQAT.IsLoaded = False Then
My.Settings.AppCmdOpenQAT_Visible = False
ElseIf MyRibbonUserControl.AppCmdopenQAT.IsLoaded = True Then
My.Settings.AppCmdOpenQAT_Visible = True
End If
If MyRibbonUserControl.AppCmdSaveAsQAT.IsLoaded = False Then
My.Settings.AppCmdSaveAsQAT_Visible = False
ElseIf MyRibbonUserControl.AppCmdSaveAsQAT.IsLoaded = True Then
My.Settings.AppCmdSaveAsQAT_Visible = True
End If
If MyRibbonUserControl.AppCmdCloseQAT.IsLoaded = False Then
My.Settings.AppCmdCloseQAT_Visible = False
ElseIf MyRibbonUserControl.AppCmdcloseQAT.IsLoaded = True Then
My.Settings.AppCmdCloseQAT_Visible = True
End If
项目设置
Winform 加载时恢复 QAT 状态
Private Sub AppForm_Load(sender As Object, e As EventArgs) Handles Me.Load
If My.Settings.AppCmdNewQAT_Visible = False Then
MyRibbonUserControl.RibbonWPF.QuickAccessToolBar.Items.Remove(MyRibbonUserControl.AppCmdNewQAT)
End If
If My.Settings.AppCmdOpenQAT_Visible = False Then
MyRibbonUserControl.RibbonWPF.QuickAccessToolBar.Items.Remove(MyRibbonUserControl.AppCmdOpenQAT)
End If
用户会话期间恢复 QAT(来自选项卡 Ribbon 设置)
VB.NET code in UserControlRibbonWPF.xaml.vb
Private Sub RestoreQAT_Click(sender As Object, e As RoutedEventArgs) _
Handles RestoreQATRibbonButton.Click
If AppCmdNewQAT.IsLoaded = False Then
RibbonWPF.QuickAccessToolBar.Items.Add(AppCmdNewQAT)
End If
If AppCmdOpenQAT.IsLoaded = False Then
RibbonWPF.QuickAccessToolBar.Items.Add(AppCmdOpenQAT)
End If
If AppCmdSaveAsQAT.IsLoaded = False Then
RibbonWPF.QuickAccessToolBar.Items.Add(AppCmdSaveAsQAT)
End If
If AppCmdCloseQAT.IsLoaded = False Then
RibbonWPF.QuickAccessToolBar.Items.Add(AppCmdCloseQAT)
End If
End Sub
已知bug
最小化 Ribbon 后,当您使用上下文菜单最大化它时,它可能不会完全显示。
作为一种解决方法,可以双击选项卡标题来最小化/最大化 Ribbon。
结论
我希望这个演示表明可以使用 WPF Ribbon 升级 Winforms 应用程序,而无需对数据结构进行太多更改。 我也认为通过命令绑定,应该可以使用一个有用的命令接口。
历史
- 2022 年 1 月 1 日 - 首次提交
- 2022 年 1 月 1 日 - 添加了下载链接