程序员的资源宝库

网站首页 > gitee 正文

动画装饰弹出控件(动画装饰弹出控件怎么设置)

sanyeah 2024-04-01 11:43:18 gitee 5 ℃ 0 评论

  • 下载sample - 83.1 KB

介绍 应用程序中的可视空间是一种优势。即使是在分辨率惊人的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

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表