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]); ;
            }
        }

 

posted @ 2019-06-21 09:30  ARM830  阅读(706)  评论(0编辑  收藏  举报