• 动画装饰弹出控件


    介绍 应用程序中的可视空间是一种优势。即使是在分辨率惊人的4K显示器时代,设计师和开发人员也总是被迫在更小的区域显示更多的信息。多年来,出现了一些新的技术来满足这些需求,例如对话框、弹出框等。向用户显示附加信息的另一种方法是使用Adorner类。Adorner类与其他控件的不同之处在于它显示在Adorner层中,该层位于应用程序中所有其他uielement的顶部。使用装饰器的困难在于没有现成的方法来显示供用户交互的控件。下面是如何克服这个小缺点的方法。可能有更优雅的解决方案,但这一个可以完成任务。 背景 有时,有些数据结构可以用简单的描述表示,但实际上包含了更广泛的数据,这会占用宝贵的屏幕空间。在过去,这是使用多文档接口(MDI)处理的,允许用户访问数据。通过WPF提供的可视化支持,我们可以通过单击显示或隐藏所有附加信息,所有这些都在应用程序的可视化显示区域内。 的PopupAdorner PopupAdorner类充当需要显示的任何附加信息的可视化容器。为了使本文简短,我没有包括任何检查装饰器在窗口中的位置的代码。 隐藏,收缩,复制Code

    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Documents;
    using System.Windows.Media;
    
    namespace UI
    {
        public class PopupAdorner : Adorner
        {
            private VisualCollection _visuals;
            private ContentPresenter _presenter;
            
            /// <summary>
            /// Creates a new popup adorner with the specified content.
            /// </summary>
            /// <paramname="adornedElement">The UIElement that will be adorned</param>
            /// <paramname="content">The content that will be display inside the popup</param>
            /// <paramname="offset">The popup position in regards to the adorned element</param>
            public PopupAdorner(UIElement adornedElement, UIElement content, Vector offset)
                : base(adornedElement)
            {
                _visuals = new VisualCollection(this);
                _presenter = new ContentPresenter();
                _visuals.Add(_presenter);
                _presenter.Content = content;
                Margin = new Thickness(offset.X, offset.Y, 0, 0);
            }
            
            protected override Size MeasureOverride(Size constraint)
            {
                _presenter.Measure(constraint);
                return _presenter.DesiredSize;
            }
            protected override Size ArrangeOverride(Size finalSize)
            {
                _presenter.Arrange(new Rect(0, 0, finalSize.Width, finalSize.Height));
                return _presenter.RenderSize;
            }
            protected override Visual GetVisualChild(int index)
            {
                return _visuals[index];
            }
            protected override int VisualChildrenCount
            {
                get
                {
                    return _visuals.Count;
                }
            }
            
            /// <summary>
            /// Brings the popup into view.
            /// </summary>
            public void Show()
            {
                AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(AdornedElement);
                adornerLayer.Add(this);
            }
            /// <summary>
            /// Removes the popup into view.
            /// </summary>
            public void Hide()
            {
                AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(AdornedElement);
                adornerLayer.Remove(this);
            }
        }
    }

    使用VisualCollection类,我们可以克服Adorner类的开箱即用设计。通过重写默认的呈现行为,我们可以在装饰器中包含任何类型的控件及其子控件。限制是我们只能有一个父对象。 定义装饰器内容 构建内容有两种方法,自定义用户控件或通过背后的代码。由于使用VS构建自定义用户控件非常简单,所以我将演示如何通过编程方式构建一个简单的控件。 隐藏,收缩,复制Code

    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Media;
    
    namespace UI
    {
        public static class DynamicAdornerContent
        {
            public static Border GetSimpleInfoPopup(string[] textInfo)
            {
                Border popupBorder = new Border() 
                    { BorderBrush = Brushes.Black, BorderThickness = new Thickness(1D) };
                Grid container = new Grid() 
                    { Background = Brushes.White };
                
                Style txtStyle = new Style();
                txtStyle.TargetType = typeof(TextBlock);
                txtStyle.Setters.Add(new Setter() 
                    { 
                        Property = FrameworkElement.HorizontalAlignmentProperty, 
                        Value = HorizontalAlignment.Left 
                    });
                txtStyle.Setters.Add(new Setter() 
                    { 
                        Property = FrameworkElement.VerticalAlignmentProperty, 
                        Value = VerticalAlignment.Center 
                    });
                
                for (int i = 0; i < textInfo.Length; ++i)
                {
                    container.RowDefintions.Add(new RowDefinition() 
                        { Height = new GridLength(26D) };
    
                    var tbox = new TextBlock();
                    tbox.Style = txtStyle;
                    tbox.Text = textInfo[i];
                    
                    Grid.SetRow(tbox, i);
                    container.Children.Add(tbox);
                }
                
                popupBorder.Child = container;
                return popupBorder;
            }
        }
    }

    使用PopupAdorner 装饰器可以用来装饰任何类型的UIElement。为此,我将构建一个自定义用户控件,其中包含一个TextBlock和一个简单的箭头图像,用户可以单击它来展开或折叠弹出装饰器。 XAML 隐藏,收缩,复制Code

    <UserControl>
        <UserControl.Resources>
            <DrawingImagex:Key="img_Arrow">
                <DrawingImage.Drawing>
                    <DrawingGroup>
                        <GeometryDrawingBrush="Gray">
                            <GeometryDrawing.Pen>
                                <PenBrush="DarkGray"EndLineCap="Round"LineJoin="Round"StartLineCap="Round"Thickness="1"/>
                            </GeometryDrawing.Pen>
                            <GeometryDrawing.Geometry>
                                <PathGeometry>
                                    <PathFigureIsFilled="True"StartPoint="0,5">
                                        <PathFigure.Segments>
                                            <LineSegmentPoint="5,0"/>
                                            <LineSegmentPoint="5,10"/>
                                            <LineSegmentPoint="0,5"/>
                                        </Pathfigure.Segments>
                                    </PathFigure>
                                </PathGeometry>
                            </GeometryDrawing.Geometry>
                        </GeometryDrawing>
                    </DrawingGroup>
                </DrawingImage.Drawing>
            </DrawingImage>
        </UserControl.Resources>
        <GridBackground="White"Height="28"Width="300"x:Name="grid_Container">
            <Grid.ColumnDefinitions>
                <ColumnDefinitionWidth="1*"/>
                <ColumnDefinitionWidth="20"/>
            </Grid.ColumnDefinitions>
            <TextBlockGrid.Column="0"HorizontalAlignment="Stretch"TextTrimming="CharacterEllipsis"TextWrapping="NoWrap"VerticalAlignment="Center"x:Name="txt_DisplayText"/>
            <ImageGrid.Column="1"Height="18"MouseDown="TogglePopup"Source="{StaticResource ResourceKey=img_Arrow}"ToolTip="Expand"Width="16"x:Name="ctl_Expander"/>
        </Grid>
    </UserControl>

    后面的代码 隐藏,收缩,复制Code

    using System;
    using System.Windows;
    using System.Windows.Controls;
    using System.Widnows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Animation;
    
    namespace UI
    {
        public class ControlWithPopup : UserControl
        {
            private Border _infoContainer;
            private PopupAdorner _infoPopup;
            private bool _isExpanded;
            
            public ControlWithPopup(string displayText, string[] additionalInfo)
            {
                InitializeComponent();
                _displayText.Text = displayText;
                _infoContainer = DynamicAdornerContent.GetSimpleInfoPopup(additionalInfo);
            }
            
            private TogglePopup(sender object, MouseButtonEventArgs e)
            {
                if (_isExpanded)
                {
                    _infoPopup.Hide();
                    _isExpanded = false;
                }
                else
                {
                    if (_infoPopup == null)
                    {
                        _infoPopup = new PopupAdorner(
                            grid_Container, 
                            _infoContainer, 
                            new Vector(0, 29));
                    }
                    
                    _infoPopup.Show();
                    _isExpanded = true;
                }
            }
        }
    }

    这样,当用户单击箭头图像时,提供的附加信息将弹出到自定义用户控件下方的视图中,然后在再次单击箭头时从视图中消失。 添加动画 此时,控件除了显示和隐藏附加信息外,并没有做任何可视化工作。我们需要的是一些动画,使过渡在视觉上更吸引人。 隐藏,收缩,复制Code

    // add these animations, transforms, and method to the ControlWithPopup class
    private DoubleAnimation _extendAnimation;
    private DoubleAnimation _collapseAnimation;
    private DoubleAnimation _extendArrowAnimation;
    private DoubleAnimation _collapseArrowAnimation;
    private RotateTransform _extendArrowTransform;
    private RotateTransform _collapseArrowTransform;
    
    // call this in the constructor to build the animations 
    // for rotating the arrow in response to user interactions
    private void InitializeAnimations()
    {
        _extendArrowAnimation = 
            new DoubleAnimation(0.0, -90.0, new Duration(TimeSpan.FromSeconds(0.25)));
        _collapseArrowAnimation = 
            new DoubleAnimation(-90.0, 0.0, new Duration(TimeSpan.FromSeconds(0.25)));
        _extendArrowTransform = 
            new RotateTransform() { Angle = -90, CenterX = 0.5, CenterY = 0.5 };
        _collapseArrowTransform = 
            new RotateTransform() { Angle = 0, CenterX = 0.5, CenterY = 0.5 };
    }
    
    // alter the TogglePopup function to include animation calls
    private TogglePopup(sender object, MouseButtonEventArgs e)
    {
        ctl_Expander.RenderTransformOrigin = new Point(0.5, 0.5);
        
        if (_isExpanded)
        {
            ctl_Expander.RenderTransform = _collapseArrowTransform;
            ctl_Expander.BeginAnimation(RotateTransform.AngleProperty, _collapseArrowAnimation);
            
            _collapseAnimation = new DoubleAnimation(
                _infoContainer.ActualHeight, 
                0.0, 
                new Duration(TimeSpan.FromSeconds(0.25)), 
                FillBehavior.Stop);
            // this next line will prevent the popup from being removed from the
            // AdornerLayer until the animation completes
            _collapseAnimation.Completed += (s, ev) => { _infoPopup.Hide(); }; 
            
            _infoPopup.BeginAnimation(HeightProperty, _collapseAnimation);
            _isExpanded = false;
        }
        else
        {
             if (_infoPopup == null)
            {
                 _infoPopup = 
                     new PopupAdorner(grid_Container, _infoContainer, new Vector(0, 29));
                 _infoContainer.Measure
                     (new Size(Double.PositiveInfinity, Double.PositiveInifity));
                 
                 _extendAnimation = new DoubleAnimation(
                    0.0, 
                    _infoContainer.DesiredSize.Height, 
                    new Duration(TimeSpan.FromSeconds(0.25)), 
                    FillBehavior.Stop);
                 
                // this line will cause the extend animation to begin after the container
                // information is loaded
                 _infoContainer.Loaded += (s, ev) => 
                    { 
                        _infoContainer.BeginAnimation(HeightProperty, _extendAnimation; 
                    }
            }
            
            ctl_Expander.RenderTransform = extendArrowTransform;
            ctl_Expander.BeginAnimation(RotateTransform.AngleProperty, _extendArrowAnimation);
            
            _infoPopup.Show();
            _isExpanded = true;
        }
    }

    这里添加的是四个DoubleAnimation对象和两个RotateTransform对象。这些动画和转换负责根据用户的需要改变视觉效果。当用户单击扩展箭头时,箭头将旋转指向下方,装饰器弹出窗口将向下滑动到视图中。当再次点击时,箭头旋转回原来的位置,弹出的装饰器滑回并退出视图,当关闭动画结束时,装饰器从装饰器层删除自己。我没有包含任何代码来检查喜欢点击的用户,如果在转换过程中单击了展开箭头,它将出错。 特殊的识别 我只是想包括链接到所有的数据来源,帮助我在这个项目: http://www.codeproject.com/articles/54472/defining - wpf装饰器- - xaml http://www.codeproject.com/articles/17696/spelling -建议-在-一个wpf文本框https://social.msdn.microsoft.com/forums/vstudio/en us/81eca7d5 - 88 d7 - 477 a - 8国开行- cfb9e8b75379/how -添加-控制- adorner?论坛= wpf http://stackoverflow.com/questions/9998691/wpf-adorner-with-controls-inside http://stackoverflow.com/questions/8576594/drawingcontext-adorner-possible-to-draw-stackpanel 历史 10/13/2016初版10/14/2016修正错误;添加示例项目 本文转载于:http://www.diyabc.com/frontweb/news455.html

  • 相关阅读:
    数据结构学习
    古兰查询 之查询页面隐藏
    Qt只QSetting
    学习下知然网友写的taskqueue
    producter-consumer 他山之石
    unix缓冲
    Buffering of C streams
    POCO Log库
    linux下open和fopen的区别
    dup2替换
  • 原文地址:https://www.cnblogs.com/Dincat/p/13450154.html
Copyright © 2020-2023  润新知