65.9K
CodeProject 正在变化。 阅读更多。
Home

WinForm VB.NET 承载 WPF Ribbon

starIconstarIconstarIconstarIconstarIcon

5.00/5 (6投票s)

2022年1月1日

CPOL

3分钟阅读

viewsIcon

9115

downloadIcon

406

在 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(在顶部)。

带有 tabcontrolRichtextboxes 的 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 日 - 添加了下载链接
© . All rights reserved.