Context menu with embedded text box

Ribbon for WPF Forum

Posted 3 months ago by Andrew Levine
Version: 19.1.0684
Avatar

I have a problem -- I'm using a PopupGallery with custom tiles that include PopupButtons, and in the PopupContent there is a text box. Once the text box is selected by the user, the PopupGallery is no longer responsive unless you hit the ESC key. Do you have any ideas how to fix this? I have a sample which I'll try to attach.

<Window
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:Sample_ContextMenu"
        xmlns:syntax="http://schemas.actiprosoftware.com/winfx/xaml/syntaxeditor" xmlns:ribbon="http://schemas.actiprosoftware.com/winfx/xaml/ribbon" x:Class="MainWindow"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>

        <syntax:SyntaxEditor x:Name="editor" DockPanel.Dock="Bottom" IsMultiLine="False"
                             >
            <syntax:SyntaxEditor.ContextMenu>
                <ribbon:ContextMenu x:Name="editorMenu"
                                            StaysOpen="True"
                            >
                    <ribbon:Menu>
                        <StackPanel >
                            <ribbon:Separator />
                            <ribbon:Menu>
                                <ribbon:PopupButton Label="Reference manual" 
                                                    StaysOpenOnClick="True"
                                                    PopupPlacement="Bottom"
                                                    >
                                    <ribbon:PopupButton.PopupContent>
                                        <ribbon:PopupGallery InitialColumnCount="5" CanFilter="True" x:Name="popupReference"
                                                                     >
                                            <ribbon:PopupGallery.CategorizedItemsSource>
                                                <x:Array Type="{x:Type local:RegexGalleryItem}">
                                                    <local:RegexGalleryItem ribbon:PopupGallery.Category="Character classes" Header="Range" Snippet="[A-Z]" 
                                                                            FullHeader="Character range"
                                                                            Description="When inside square braces, match any letter between two that are separated by a hyphen."
                                                                            Sample="The quick brown Fox jumped over the Lazy Dog."
                                                                            />
                                                    <local:RegexGalleryItem ribbon:PopupGallery.Category="Character classes" Header="Set" Snippet="[abc]" Positive="True" 
                                                                                    FullHeader="Character set"
                                                                                    Description="Match any letter or range of letters appearing between the brackets."
                                                                                    />
                                                    <local:RegexGalleryItem ribbon:PopupGallery.Category="Character classes" Header="Not" Snippet="[^a-w]" Negative="True"
                                                                                    FullHeader="Inverse character set"
                                                                                    Description="Match any letter other than the ones appearing between the brackets."
                                                                                    />
                                                    <local:RegexGalleryItem ribbon:PopupGallery.Category="Character classes" Header="Wildcard" Snippet="." 
                                                                                    Sample="abcdefGHIJKL01234&amp;@()\n\n123"
                                                                                    FullHeader="Any character"
                                                                                    Description="Match any letter other than a line feed."
                                                                                    />
                                                    <local:RegexGalleryItem ribbon:PopupGallery.Category="Character classes" Header="Word" Snippet="\w" Positive="True"/>
                                                    <local:RegexGalleryItem ribbon:PopupGallery.Category="Character classes" Header="Not word" Snippet="\W" Negative="True"/>
                                                    <local:RegexGalleryItem ribbon:PopupGallery.Category="Character classes" Header="Digit" Snippet="\d" Positive="True"/>
                                                    <local:RegexGalleryItem ribbon:PopupGallery.Category="Character classes" Header="Not digit" Snippet="\D" Negative="True" />
                                                    <local:RegexGalleryItem ribbon:PopupGallery.Category="Anchors" Header="Start" Snippet="^" SnippetOverride="^.{5}" />
                                                    <local:RegexGalleryItem ribbon:PopupGallery.Category="Anchors" Header="End" Snippet="$" SnippetOverride=".{5}$"/>
                                                    <local:RegexGalleryItem ribbon:PopupGallery.Category="Anchors" Header="Boundary" Snippet="\b" Positive="True" SnippetOverride=".\b."/>
                                                    <local:RegexGalleryItem ribbon:PopupGallery.Category="Anchors" Header="Unboundary" Snippet="\B" Negative="True" SnippetOverride=".\B."/>
                                                    <local:RegexGalleryItem ribbon:PopupGallery.Category="Escaped characters" Header="Escape" Snippet="\*" />
                                                    <local:RegexGalleryItem ribbon:PopupGallery.Category="Escaped characters" Header="Octal" Snippet="\000" />
                                                    <local:RegexGalleryItem ribbon:PopupGallery.Category="Escaped characters" Header="Hex" Snippet="\xFF" />
                                                    <local:RegexGalleryItem ribbon:PopupGallery.Category="Escaped characters" Header="Unicode" Snippet="\uFFFF" />
                                                    <local:RegexGalleryItem ribbon:PopupGallery.Category="Escaped characters" Header="CTRL" Snippet="\cI" />
                                                    <local:RegexGalleryItem ribbon:PopupGallery.Category="Escaped characters" Header="Tab" Snippet="\t" />
                                                    <local:RegexGalleryItem ribbon:PopupGallery.Category="Escaped characters" Header="Vertical tab" Snippet="\v" />
                                                    <local:RegexGalleryItem ribbon:PopupGallery.Category="Escaped characters" Header="Line feed" Snippet="\n" />
                                                    <local:RegexGalleryItem ribbon:PopupGallery.Category="Groups and backreferences" Header="Group" Snippet="(fox)" />
                                                    <local:RegexGalleryItem ribbon:PopupGallery.Category="Groups and backreferences" Header="Named" Snippet="(?&lt;name&gt;ABC)"  />
                                                    <local:RegexGalleryItem ribbon:PopupGallery.Category="Groups and backreferences" Header="Numeric" Snippet="\1" SnippetOverride="([foxdg]{3})\1" />
                                                    <local:RegexGalleryItem ribbon:PopupGallery.Category="Groups and backreferences" Header="Uncaptured" Snippet="(?:ABC)" />
                                                    <local:RegexGalleryItem ribbon:PopupGallery.Category="Lookaround" Header="Lookahead" Snippet="(?=ABC)" Positive="True" SnippetOverride="a(?=ABC)"/>
                                                    <local:RegexGalleryItem ribbon:PopupGallery.Category="Lookaround" Header="Lookahead" Snippet="(?!ABC)" Negative="True" SnippetOverride="a(?!ABC)"/>
                                                    <local:RegexGalleryItem ribbon:PopupGallery.Category="Lookaround" Header="Lookbehind" Snippet="(?&lt;=ABC)" Positive="True" SnippetOverride="(?&lt;=ABC)a"/>
                                                    <local:RegexGalleryItem ribbon:PopupGallery.Category="Lookaround" Header="Lookbehind" Snippet="(?&lt;!ABC)" Negative="True" SnippetOverride="(?&lt;!ABC)a"/>
                                                    <local:RegexGalleryItem ribbon:PopupGallery.Category="Quantifiers and logic" Header="Optional" Snippet="?" SnippetOverride=".?" />
                                                    <local:RegexGalleryItem ribbon:PopupGallery.Category="Quantifiers and logic" Header="Zero or more" Snippet="*" SnippetOverride=".*"/>
                                                    <local:RegexGalleryItem ribbon:PopupGallery.Category="Quantifiers and logic" Header="One or more" Snippet="+" SnippetOverride=".+"/>
                                                    <local:RegexGalleryItem ribbon:PopupGallery.Category="Quantifiers and logic" Header="Between" Snippet="{}{1,3}" SnippetOverride=".{1,3}" />
                                                    <local:RegexGalleryItem ribbon:PopupGallery.Category="Quantifiers and logic" Header="Lazy" Snippet="?" SnippetOverride="fo?x"/>
                                                    <local:RegexGalleryItem ribbon:PopupGallery.Category="Quantifiers and logic" Header="OR" Snippet="|" SnippetOverride="fox|dog" />
                                                </x:Array>
                                            </ribbon:PopupGallery.CategorizedItemsSource>
                                        </ribbon:PopupGallery>
                                    </ribbon:PopupButton.PopupContent>
                                </ribbon:PopupButton>
                            </ribbon:Menu>
                        </StackPanel>
                    </ribbon:Menu>
                </ribbon:ContextMenu>
            </syntax:SyntaxEditor.ContextMenu>
            <syntax:EditorDocument x:Name="regexDocument" xml:space="preserve" Text="asdf"/>
        </syntax:SyntaxEditor>

    </Grid>
</Window>
Imports ActiproSoftware.Windows.Controls.SyntaxEditor
Imports ActiproSoftware.Windows.Controls.SyntaxEditor.Implementation
Imports System.Text.RegularExpressions
Imports ActiproSoftware.Windows.Controls
Imports ActiproSoftware.Text.Searching
Imports ActiproSoftware.Windows.Controls.Ribbon.Controls.Primitives

Class MainWindow

End Class
Public Class RegexGalleryItem
    Inherits ActiproSoftware.Windows.Controls.Ribbon.Controls.GalleryItem
    Private myHeader As String
    Private myDescription As String
    Private mySnippet As String, myNegative As Boolean, myPositive As Boolean, mySample As String, mySnippetOverride As String, myFullHeader As String
    Private headerTextblock As TextBlock, snippetTextblock As TextBlock, mainGrid As Grid, stackPanel As Windows.Controls.StackPanel
    Private popupBtn As ActiproSoftware.Windows.Controls.Ribbon.Controls.PopupButton, tipFooter As SyntaxEditor, tipTitle As TextBlock, tipDescription As TextBlock
    Private tipSearch As ActiproSoftware.Windows.Controls.Ribbon.Controls.TextBox
    Private Shared lastPopup As ActiproSoftware.Windows.Controls.Ribbon.Controls.PopupButton
    Private defaultSelection As ActiproSoftware.Windows.Controls.Ribbon.Controls.Primitives.PopupGalleryFilterButton
    Protected Shared ReadOnly Property GenericSample As String
        Get
            Return "The quick brown fox jumped over the lazy dog."
        End Get
    End Property
    Sub New()
        MyBase.New
        Me.Width = 75
        Me.Height = 60
        AddHandler Me.MouseEnter, AddressOf OpenDetails
        AddHandler Me.MouseDoubleClick, AddressOf popupReference_MouseDoubleClick
    End Sub
    Private Sub popupReference_MouseDoubleClick(sender As Object, e As MouseButtonEventArgs)
        MsgBox("INVOKEKIND")
    End Sub

    Friend Sub OpenPopup()
        lastPopup = popupBtn
        popupBtn.IsPopupOpen = True
    End Sub
    Friend Shared Sub ClosePopup()
        If Not lastPopup Is Nothing Then lastPopup.IsPopupOpen = False
    End Sub
    Private Sub OpenDetails(sender As Object, e As RoutedEventArgs)
        OpenPopup()
        e.Handled = True
    End Sub
    Private Sub CloseDetails(sender As Object, e As RoutedEventArgs)
        popupBtn.IsEnabled = False
    End Sub

    Public Property FullHeader As String
        Get
            Return myFullHeader
        End Get
        Set(value As String)
            myFullHeader = value
            UpdateContent()
        End Set
    End Property
    Public Property Sample As String
        Get
            If mySample = "" Then Return RegexGalleryItem.GenericSample
            Return mySample
        End Get
        Set(value As String)
            mySample = value
            UpdateContent()
        End Set
    End Property
    Public Property Snippet As String
        Get
            Return mySnippet
        End Get
        Set(value As String)
            mySnippet = value
            UpdateContent()
        End Set
    End Property
    Public Property SnippetOverride As String
        Get
            If String.IsNullOrEmpty(mySnippetOverride) Then Return mySnippet
            Return mySnippetOverride
        End Get
        Set(value As String)
            mySnippetOverride = value
            UpdateContent()
        End Set
    End Property
    Public Property Header As String
        Get
            Return myHeader
        End Get
        Set(value As String)
            myHeader = value
            UpdateContent()
        End Set
    End Property
    Public Property Description As String
        Get
            Return myDescription
        End Get
        Set(value As String)
            myDescription = value
            UpdateContent()
        End Set
    End Property
    Public Property Negative As Boolean
        Get
            Return myNegative
        End Get
        Set(value As Boolean)
            myNegative = value
            UpdateContent()
        End Set
    End Property
    Public Property Positive As Boolean
        Get
            Return myPositive
        End Get
        Set(value As Boolean)
            myPositive = value
            UpdateContent()
        End Set
    End Property
    Private Sub UpdateContent()
        If mainGrid Is Nothing Then
            mainGrid = New Grid
            mainGrid.VerticalAlignment = VerticalAlignment.Center
            stackPanel = New Windows.Controls.StackPanel
            stackPanel.Orientation = Windows.Controls.Orientation.Vertical
            stackPanel.IsHitTestVisible = False
            headerTextblock = New TextBlock
            headerTextblock.HorizontalAlignment = HorizontalAlignment.Center
            headerTextblock.FontWeight = FontWeight.FromOpenTypeWeight(700)
            headerTextblock.VerticalAlignment = VerticalAlignment.Bottom
            headerTextblock.Height = 24
            headerTextblock.TextWrapping = TextWrapping.Wrap
            stackPanel.Children.Add(headerTextblock)
            snippetTextblock = New TextBlock
            snippetTextblock.HorizontalAlignment = HorizontalAlignment.Center
            stackPanel.Children.Add(snippetTextblock)
            tipFooter = New SyntaxEditor
            tipFooter.HorizontalScrollBarVisibility = ScrollBarVisibility.Hidden
            tipFooter.VerticalScrollBarVisibility = ScrollBarVisibility.Hidden
            tipFooter.Height = 100
            tipFooter.HorizontalAlignment = HorizontalAlignment.Stretch
            tipFooter.IsLineNumberMarginVisible = False
            tipFooter.IsIndicatorMarginVisible = False
            tipFooter.IsSelectionMarginVisible = False
            tipFooter.IsOutliningMarginVisible = False
            tipFooter.IsRulerMarginVisible = False
            tipFooter.WordWrapMode = WordWrapMode.Word
            tipFooter.Background = Windows.Media.Brushes.Black
            tipFooter.Foreground = Windows.Media.Brushes.LightGreen
            tipFooter.FontFamily = New Media.FontFamily("Courier New")
            tipFooter.FontSize = 20
            tipFooter.FontWeight = FontWeight.FromOpenTypeWeight(900)
            tipFooter.Margin = New Thickness(3)
            tipFooter.IsEnabled = False
            Dim menu As New Windows.Controls.StackPanel
            menu.Orientation = Orientation.Vertical
            popupBtn = New ActiproSoftware.Windows.Controls.Ribbon.Controls.PopupButton
            popupBtn.VariantSize = Ribbon.Controls.VariantSize.Large
            popupBtn.PopupContent = menu
            popupBtn.PopupPlacement = Windows.Controls.Primitives.PlacementMode.Top
            popupBtn.StaysOpenOnClick = True
            'popupBtn.ClickMode = ClickMode.Hover
            'AddHandler popupBtn.MouseLeave, AddressOf popupReference_PreviewMouseDown
            tipTitle = New TextBlock
            tipDescription = New TextBlock
            tipTitle.FontWeight = FontWeight.FromOpenTypeWeight(800)
            tipDescription.TextWrapping = TextWrapping.Wrap
            tipTitle.FontSize = 14
            tipDescription.FontSize = 13
            tipTitle.Margin = New Thickness(10)
            tipDescription.Margin = New Thickness(10)
            menu.Children.Add(tipTitle)
            menu.Children.Add(tipDescription)
            Dim dp As New Grid
            tipSearch = New ActiproSoftware.Windows.Controls.Ribbon.Controls.TextBox
            tipSearch.Width = 40
            tipSearch.HorizontalAlignment = HorizontalAlignment.Right
            tipSearch.VerticalAlignment = VerticalAlignment.Bottom
            dp.Children.Add(tipFooter)
            dp.Children.Add(tipSearch)
            menu.Children.Add(dp)
            menu.Width = 300
            mainGrid.Children.Add(popupBtn)
            mainGrid.Children.Add(stackPanel)
            Content = mainGrid
        End If
        headerTextblock.Text = Header
        If Negative Then headerTextblock.Foreground = Windows.Media.Brushes.Red
        If Positive Then headerTextblock.Foreground = Windows.Media.Brushes.Green
        snippetTextblock.Text = Snippet
        tipTitle.Text = FullHeader
        tipDescription.Text = Description
        tipFooter.Text = Sample
        tipSearch.Text = SnippetOverride
        TipSearchChanged(Nothing, Nothing)
    End Sub

    Sub TipSearchChanged(sender As Object, e As KeyboardEventArgs)
        Dim r As String
        Try
            Dim regex As New Regex(tipSearch.Text)
            r = tipSearch.Text
            tipSearch.Background = Media.Brushes.White
        Catch ex As Exception
            r = ""
            tipSearch.Background = Media.Brushes.Salmon
        End Try

        Dim options As New EditorSearchOptions()
        options.FindText = r
        options.PatternProvider = SearchPatternProviders.RegularExpression
        tipFooter.ActiveView.HighlightedResultSearchOptions = options
    End Sub

End Class

[Modified 3 months ago]

Comments (1)

Posted 3 months ago by Andrew Levine
Avatar

Never mind, I was able to find a workaround by setting the popupReference.PreviewMouseMove like so:

    Private Sub popupReference_PreviewMouseMove(sender As Object, e As Windows.Input.MouseEventArgs)
        Dim el As DependencyObject = TryCast(popupReference.InputHitTest(e.GetPosition(popupReference)), DependencyObject)
        If el Is Nothing Then Exit Sub
        Dim item As RegexGalleryItem = MainWindow.FindVisualParent(el, GetType(RegexGalleryItem))
        If item Is Nothing Then Exit Sub
        Dim btn As PopupGallery = MainWindow.FindVisualParent(e.OriginalSource, GetType(PopupGallery))
        If btn Is Nothing Then Exit Sub
        item.OpenPopup()

    End Sub
The latest build of this product (v2020.1.1) was released 15 days ago, which was after the last post in this thread.

Add Comment

Please log in to a validated account to post comments.