xaml - 将 MenuFlyout 添加到 RichEditBox UWP

标签 xaml win-universal-app uwp uwp-xaml richeditbox

除了已有的弹出项目之外,是否可以向 UWP 中的 RichEditBox 添加菜单弹出项目。但我发现 richeditbox 中没有弹出属性。那么可以加一个吗?如果是,请提供添加 menuFlyout 的步骤。提前致谢!

最佳答案

当然有可能。

 <RichEditBox GotFocus="RichEditBox_GotFocus">
                    <FlyoutBase.AttachedFlyout>
                        <Flyout>
                            <Button Content="test"/>
                        </Flyout>
                    </FlyoutBase.AttachedFlyout>
                </RichEditBox>

 private void RichEditBox_GotFocus(object sender, RoutedEventArgs e)
        {
            FlyoutBase.ShowAttachedFlyout((sender as RichEditBox));
        }

更新

我尝试在没有自定义弹出窗口的情况下实现您的要求。

观察

1 RightTapped 事件不会针对 Textbox 触发。不知道为什么。那里 是 TextBoxControlTemplate 中的 ScrollViewer (可能是 RightTapped 事件未在文本框中触发的原因)所以我添加了 Scrollviewer 的 RightTapped 事件。

2.

   private async void ContentElement_RightTapped(object sender, RightTappedRoutedEventArgs e)
            {
                FlyoutBase.ShowAttachedFlyout(textbox);
                 await  Task.Delay(1000);
                FlyoutPresenter canvas = testbutton.FindParent<FlyoutPresenter>();
                var popup = canvas.Parent as Popup;

                double x = e.GetPosition(e.OriginalSource as UIElement).X;
                Debug.WriteLine(x);
                popup.IsOpen = false;
                popup.SetValue(Canvas.LeftProperty, e.GetPosition(e.OriginalSource as  UIElement).X);
                popup.IsOpen = true;
            }


 <Style x:Key="RichEditBoxStyle1" TargetType="RichEditBox">
    ...
     <ScrollViewer x:Name="ContentElement" IsRightTapEnabled="True" RightTapped="ContentElement_RightTapped"  AutomationProperties.AccessibilityView="Raw" HorizontalScrollMode="{TemplateBinding ScrollViewer.HorizontalScrollMode}" HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}" IsTabStop="False" IsHorizontalRailEnabled="{TemplateBinding ScrollViewer.IsHorizontalRailEnabled}" IsVerticalRailEnabled="{TemplateBinding ScrollViewer.IsVerticalRailEnabled}" IsDeferredScrollingEnabled="{TemplateBinding ScrollViewer.IsDeferredScrollingEnabled}" Margin="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}" Grid.Row="1" VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}" VerticalScrollMode="{TemplateBinding ScrollViewer.VerticalScrollMode}" ZoomMode="Disabled"/>
...
    </Style>
    <RichEditBox x:Name="textbox" Width="400" HorizontalAlignment="Left"  Grid.Row="3" RightTapped="RichEditBox_RightTapped" IsRightTapEnabled="True" GotFocus="RichEditBox_GotFocus" Style="{StaticResource RichEditBoxStyle1}">
                        <FlyoutBase.AttachedFlyout>
                               <Flyout >
                                <Button Content="test" x:Name="testbutton"            Click="Button_Click"/>   
                            </Flyout>
                        </FlyoutBase.AttachedFlyout>                        
                    </RichEditBox>

上面的代码中ContentElement_RightTapped是ScrollViewer的RightTapped事件。要添加此内容,您必须编辑文本框的样式。 基本上,弹出窗口包含我使用 VisualTreeHelper 获得的弹出窗口。并设置 PopUp 的位置(我从事件中获得)。但不知何故 PopUp 没有设置到准确的位置。

所以第二个选择是使用自定义弹出按钮。引用这个Link了解如何实现其中之一。您可以从那里获取代码 下面是修改后的代码

     public class TemplatedFlyout:DependencyObject
        {
            public TemplatedFlyout()
            {

            }
            Popup popUp;
            FrameworkElement senderElement;
            FrameworkElement frameworkContent;
            bool keyboardOpen = false;
            InputPane keyboard;
            public void Initialization(UIElement sender)
            {
                senderElement = sender as FrameworkElement;
                senderElement.DataContextChanged += (s, e) =>frameworkContent.DataContext = senderElement.DataContext;
                popUp = new Popup()
                {
                    ChildTransitions = new Windows.UI.Xaml.Media.Animation.TransitionCollection(),
                    IsLightDismissEnabled = true
                };
                popUp.ChildTransitions.Add(new PaneThemeTransition() { Edge = EdgeTransitionLocation.Bottom });
                frameworkContent = Template as FrameworkElement;
                frameworkContent.DataContext = senderElement.DataContext;
                popUp.Child = frameworkContent;
                FocusKeeper();
             if(sender is RichEditBox || sender is TextBox)
                {
                    (sender as FrameworkElement).Loaded += TemplatedFlyout_Loaded;
                }
             //else
             //       sender.Tapped += (s, e) => Show(e);
            }

            private void TemplatedFlyout_Loaded(object sender, RoutedEventArgs e)
            {
                (sender as FrameworkElement).FindElementInVisualTree<ScrollViewer>().RightTapped += (s, e1) => Show(e1);
            }

           public static readonly DependencyProperty TemplateProperty = DependencyProperty.Register(nameof(Template), typeof(object), typeof(TemplatedFlyout), new PropertyMetadata(null));
            public object Template
            {
                get { return (object) GetValue(TemplateProperty); }
                set { SetValue(TemplateProperty, value); }
            }       
             void FocusKeeper()
            {
                keyboard = InputPane.GetForCurrentView();
                popUp.Closed += (s, e) =>
                {
                    if(keyboardOpen)
                    {
                        popUp.IsOpen = true;
                    }
                };
                if(keyboard!=null)
                {
                    keyboard.Showing += (s, e) => keyboardOpen = true;
                    keyboard.Hiding += (s, e) => keyboardOpen = false;
                }
            }
            public async void Show(RightTappedRoutedEventArgs args)
            {
                try
                {
                   popUp.RequestedTheme = ((Window.Current.Content as Frame).Content as Page).RequestedTheme;
                    popUp.IsOpen = true;
                    frameworkContent.UpdateLayout();
                    var top = Math.Abs(senderElement.ActualHeight+frameworkContent.ActualHeight+10-Window.Current.Bounds.Height);
                    var left = args.GetPosition(args.OriginalSource as UIElement).X;                
                    if (frameworkContent is Panel)
                    {
                        var panel = frameworkContent as Panel;
                        if (panel.Children.Any())
                        {
                            if (panel.Children.First() is Control)
                            {
                                (panel.Children.First() as Control).Focus(FocusState.Keyboard);
                            }
                        }
                    }                
                    popUp.SetValue(Canvas.TopProperty, top);
                    popUp.SetValue(Canvas.LeftProperty, left);

                }
                catch(Exception e)
                {

                }
            }       
        }

  public class Extensions:DependencyObject
    {

        public static void SetFlyout(UIElement element, TemplatedFlyout value)
        {
            element.SetValue(FlyoutProperty, value);
        }
        public static TemplatedFlyout GetFlyout(UIElement element)
        {
            return (TemplatedFlyout)element.GetValue(FlyoutProperty);
        }
        public static readonly DependencyProperty FlyoutProperty = DependencyProperty.Register(nameof(FlyoutProperty), typeof(TemplatedFlyout), typeof(Extensions), new PropertyMetadata(null, TemplateFlyoutChanged));

        private static void TemplateFlyoutChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var uiSender = d as UIElement;
            var flyout = e.NewValue as TemplatedFlyout;
            flyout.Initialization(uiSender);
        }
    }
    public static class VisualExtensions
    {       
        public static T FindElementInVisualTree<T>(this DependencyObject parentElement) where T : DependencyObject
        {
            var count = VisualTreeHelper.GetChildrenCount(parentElement);
            if (count == 0) return null;

            for (int i = 0; i < count; i++)
            {
                var child = VisualTreeHelper.GetChild(parentElement, i);
                if (child != null && child is T)
                    return (T)child;
                else
                {
                    var result = FindElementInVisualTree<T>(child);
                    if (result != null)
                        return result;
                }
            }
            return null;
        }
    }


<RichEditBox  IsRightTapEnabled="True"  >
                <local:Extensions.Flyout>
                    <local:TemplatedFlyout >
                        <local:TemplatedFlyout.Template>
                            <StackPanel>
                                <TextBlock Text="test1"/>
                                <TextBlock Text="test1"/>
                            </StackPanel>
                        </local:TemplatedFlyout.Template>
                    </local:TemplatedFlyout>
                </local:Extensions.Flyout>
            </RichEditBox>

更新2

您无法添加到文本框的现有上下文菜单。要修改这里的上下文菜单是sample

关于xaml - 将 MenuFlyout 添加到 RichEditBox UWP,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37807730/

相关文章:

c# - 如何在 Win10 的新 Outlook 应用程序中实现滑动手势?

c# - UWP 拖放自定义类型/类

uwp - 组合框的默认选定索引使我的 UWP 应用程序崩溃

uwp - 如何在 ConsoleApp 中添加对 Windows.Foundation.FoundationContract 的引用以解析类型 IPropertySet

c# - 在 Windows 10 中共享目标 Universal Apps Template10 方法

uwp - VS 2017 社区 : Change target for existing project to ARM

c# - 通过 CommandParameter 传递数据

c# - 区分x :Name and Name in Wpf application

c# - XAML 给出加载失败错误

wpf - WPF 中的焦点数据模板