前面給大伙兒簡單介紹了RichEditBox控件的基本用法,以及解決其中的一些小問題。
本文咱們來看看如何自定義RichEditBox控件的上下文菜單。
原理比較簡單,所以先說一說原理。當RichEditBox控件的上下文菜單即將彈出時,會引發ContextMenuOpening事件,我們需要處理該事件,並且將e.Handled屬性設置為true,這樣才能阻止默認上下文菜單的彈出。
首先,在RichEditBox控件上聲明附加的菜單項,樣板XAML如下:
<RichEditBox Name="redit" ContextMenuOpening="OnContextMenuOpening"> <FlyoutBase.AttachedFlyout> <MenuFlyout> <MenuFlyoutItem Text="復制" Click="OnCopy"/> <MenuFlyoutItem Text="剪切" Click="OnCut"/> <MenuFlyoutItem Text="粘貼" Click="OnPaste"/> <MenuFlyoutSeparator/> <MenuFlyoutSubItem Text="字號"> <MenuFlyoutItem Text="16" Tag="16" Click="OnFontSize" /> <MenuFlyoutItem Text="20" Tag="20" Click="OnFontSize"/> <MenuFlyoutItem Text="24" Tag="24" Click="OnFontSize" /> <MenuFlyoutItem Text="36" Tag="36" Click="OnFontSize"/> <MenuFlyoutItem Text="48" Tag="48" Click="OnFontSize"/> </MenuFlyoutSubItem> <MenuFlyoutSeparator/> <ToggleMenuFlyoutItem Text="加粗" Click="OnBold" /> <MenuFlyoutSeparator/> <MenuFlyoutSubItem Text="下划線"> <MenuFlyoutItem Text="無" Tag="-1" Click="OnUnderline" /> <MenuFlyoutItem Text="單實線" Tag="0" Click="OnUnderline"/> <MenuFlyoutItem Text="雙實線" Tag="1" Click="OnUnderline"/> <MenuFlyoutItem Text="虛線" Tag="2" Click="OnUnderline"/> </MenuFlyoutSubItem> </MenuFlyout> </FlyoutBase.AttachedFlyout> </RichEditBox>
通過FlyoutBase類的AttachedFlyout附加屬性,可以將派出自FlyoutBase的彈出對象附加到任意的可視化對象上,由於這里咱們用的菜單,所以附加到RichEditBox控件的彈出對象為MenuFlyout實例。
處理ContextMenuOpening事件,阻止彈出默認的上下文菜單,然后,調用ShowAt方法在指定的坐標處打開菜單。
e.Handled = true; MenuFlyout menu = FlyoutBase.GetAttachedFlyout(redit) as MenuFlyout; menu?.ShowAt(redit, new Point(e.CursorLeft, e.CursorTop));
前面在XAML文檔中已通過FlyoutBase的AttachedFlyout附加屬性設置了MenuFlyout對象,故此處通過 GetAttachedFlyout方法,可以獲取到MenuFlyout實例的引用。
然后調用ShowAt方法來顯示菜單,之所以會調用這個方法,是因為它可以自行指定菜單彈出的位置坐標值。ContextMenuOpening事件的參數e的CursorLeft和CursorTop屬性可以得到當前指針的橫坐標和縱坐標,再把坐標傳給ShowAt方法即可以確定菜單彈出的位置。
下面代碼處理文檔的復制、剪切和粘貼功能。
private void OnCopy(object sender, RoutedEventArgs e) { redit.Document.Selection.Copy(); } private void OnCut(object sender, RoutedEventArgs e) { redit.Document.Selection.Cut(); } private void OnPaste(object sender, RoutedEventArgs e) { // Paste方法帶有一個整型參數,表示要粘貼的格式 redit.Document.Selection.Paste(0); }
被編輯文檔的Selection屬性表示文檔中正處於選擇狀態下的文本區域,通常上下文菜單只控制被選的文本,如果當前文檔沒有選定文本,那么選區就是插入光標所在的位置。
注意,在粘貼文本時,Paste方法需要一個整數值參數,指定粘貼的格式,0表示自動采用最優格式的文本,常常是RTF文本。有關格式的數值定義請自己參考https://msdn.microsoft.com/en-us/library/windows/desktop/ff729168(v=vs.85).aspx,MSDN是萬能的。
最后是設置字號、加粗、下划線功能的實現。
private void OnFontSize(object sender, RoutedEventArgs e) { MenuFlyoutItem item = sender as MenuFlyoutItem; // 獲取字號 float size = Convert.ToSingle(item.Tag); redit.Document.Selection.CharacterFormat.Size = size; } private void OnBold(object sender, RoutedEventArgs e) { ToggleMenuFlyoutItem item = sender as ToggleMenuFlyoutItem; redit.Document.Selection.CharacterFormat.Bold = item.IsChecked ? FormatEffect.On : FormatEffect.Off; } private void OnUnderline(object sender, RoutedEventArgs e) { MenuFlyoutItem item = sender as MenuFlyoutItem; int x = Convert.ToInt32(item.Tag); UnderlineType unlinetp; switch (x) { case -1: // 無 unlinetp = UnderlineType.None; break; case 0: // 單實線 unlinetp = UnderlineType.Single; break; case 1: // 雙實線 unlinetp = UnderlineType.Double; break; case 2: // 虛線 unlinetp = UnderlineType.Dash; break; default: unlinetp = UnderlineType.None; break; } redit.Document.Selection.CharacterFormat.Underline = unlinetp; }
運行應用程序,最終效果如下。
OK,本次任務完成,3166。