WPF Adorner 弹出式工具栏 例子
源于MSDN 一个问题。
问:如何做出类似word的文字选中后工具栏弹出和动画效果。
我用的是adorner,其实用popup也是可以的。
效果图:
中间黑色部分代表真正的工具栏。
xaml代码:
<Window x:Class="ADO_TOOL.MainWindow" 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:ADO_TOOL" mc:Ignorable="d" Title="MainWindow" Height="450" Width="800"> <Grid x:Name="adohost"> <RichTextBox LostKeyboardFocus="RTB_LostKeyboardFocus" VerticalAlignment="Center" x:Name="RTB" PreviewMouseLeftButtonUp="RichTextBox_PreviewMouseLeftButtonUp" > <FlowDocument > <Paragraph > <Run Text="测试显示tool"/> </Paragraph> </FlowDocument> </RichTextBox> </Grid> </Window>
adoner代码类
using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Media; namespace ADO_TOOL { public class ado_Gird : Adorner { private VisualCollection collection; protected override int VisualChildrenCount => collection.Count; protected override Visual GetVisualChild(int index) => collection[index]; protected override Size MeasureOverride(Size constraint) => base.MeasureOverride(constraint); protected override Size ArrangeOverride(Size finalSize) { _gird.Arrange(new Rect(finalSize)); var f = host as FrameworkElement; _gird.Margin = new Thickness(left, 0-top-_gird.Height,0,0); return base.ArrangeOverride(finalSize); } private Grid _gird; private UIElement host; private double left; private double top; public ado_Gird(UIElement adornedElement,double left,double top) :this(adornedElement) { this.left= left; this.top = top; } //h1是外部grid-内部grid的平均高度 //h2是外部grid-内部grid的平均宽度 readonly int h1 = 20,h2=24; public ado_Gird(UIElement adornedElement) : base(adornedElement) { collection = new VisualCollection(this); host = adornedElement; this._gird = new Grid(); _gird.Height = 50; _gird.Width = 128; _gird.HorizontalAlignment = HorizontalAlignment.Left; _gird.Background = new SolidColorBrush(Colors.Red); Grid g2 = new Grid(); g2.Height = 10; g2.Width = 80; g2.Background = new SolidColorBrush(Colors.Black); _gird.Children.Add(g2); _gird.MouseMove += _gird_MouseMove; _gird.MouseLeave += _gird_MouseLeave; _gird.Opacity = 0.5; collection.Add(_gird); } private void _gird_MouseLeave(object sender, System.Windows.Input.MouseEventArgs e) { _gird.Opacity = 0.1; } private void _gird_MouseMove(object sender, System.Windows.Input.MouseEventArgs e) { var point = e.GetPosition(_gird); var f = host as FrameworkElement; if (_gird.Width - point.X <= h2) { _gird.Opacity = 1-((h2 -( _gird.Width - point.X)) / h2); } if(_gird.Height - point.Y <= h1) { _gird.Opacity = 1 - ((h1 - (_gird.Height - point.Y)) / h1); } if (point.X>0&&point.X<=h2) { _gird.Opacity = 1-((h2 - point.X) / h2); } if (point.Y > 0 && point.Y <= h1) { _gird.Opacity = 1 - (h1 - point.Y) / h1; } } } }
xaml.cs页面代码:
AdornerLayer layer; private void RichTextBox_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e) { var point = e.GetPosition(RTB); if (layer != null) { var b = layer.GetAdorners(adohost); if(b!=null) if(b.Count()>0) layer.Remove(b[0]); } layer = AdornerLayer.GetAdornerLayer(adohost); var ado = new ado_Gird(adohost, point.X,RTB.ActualHeight); layer.Add(ado); } private void RTB_LostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e) { if (layer != null) { var b = layer.GetAdorners(adohost); if (b != null) if (b.Count() > 0) layer.Remove(b[0]); ; } }