UWP 下拉刷新控件(PullToRefreshControl)

简介: 原文:UWP 下拉刷新控件(PullToRefreshControl)最近项目里面有下拉刷新的需求,自己做了一个,效果还不错。 ...
原文: UWP 下拉刷新控件(PullToRefreshControl)

最近项目里面有下拉刷新的需求,自己做了一个,效果还不错。

  <Style TargetType="local:PullToRefreshControl">
        <Setter Property="HeaderTemplate">
            <Setter.Value>
                <DataTemplate>
                    <Grid>
                        <StackPanel VerticalAlignment="Center" Orientation="Horizontal" Visibility="{Binding IsReachThreshold,Converter={StaticResource InversedBooleanToVisibilityConverter}}">
                            <FontIcon FontSize="30"  FontFamily="Segoe UI Emoji" Glyph="" IsHitTestVisible="False"  VerticalAlignment="Bottom"/>
                            <TextBlock Margin="5,0,5,0" Text="下拉刷新" VerticalAlignment="Bottom"/>
                        </StackPanel>
                        <StackPanel VerticalAlignment="Center" Orientation="Horizontal" Visibility="{Binding IsReachThreshold, Converter={StaticResource BooleanToVisibilityConverter}}">
                            <FontIcon FontSize="30"   FontFamily="Segoe UI Emoji" Glyph="" IsHitTestVisible="False" VerticalAlignment="Bottom"/>
                            <TextBlock Margin="5,0,5,0" Text="释放立即刷新" VerticalAlignment="Bottom"/>
                        </StackPanel>
                    </Grid>
                </DataTemplate>
            </Setter.Value>
        </Setter>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="local:PullToRefreshControl">
                    <Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Margin="{TemplateBinding Margin}">
                        <ScrollViewer x:Name="ScrollViewer"
                                      VerticalScrollBarVisibility="Hidden">
                            <StackPanel>
                                <ContentControl x:Name="PanelHeader" ContentTemplate="{TemplateBinding HeaderTemplate}" HorizontalContentAlignment="Center" VerticalContentAlignment="Bottom" />
                                <ContentPresenter x:Name="PanelContent" ContentTemplate="{TemplateBinding ContentTemplate}" ContentTransitions="{TemplateBinding ContentTransitions}" Content="{TemplateBinding Content}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                            </StackPanel>
                        </ScrollViewer>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
 [TemplatePart(Name = PanelHeader, Type = typeof(ContentControl))]
    [TemplatePart(Name = PanelContent, Type = typeof(ContentPresenter))]
    [TemplatePart(Name = ScrollViewer, Type = typeof(ScrollViewer))]
    public class PullToRefreshControl:ContentControl
    {
        #region Fields
        private const string PanelHeader = "PanelHeader";
        private const string PanelContent = "PanelContent";
        private const string ScrollViewer = "ScrollViewer";
        private ContentControl _panelHeader;
        private ContentPresenter _panelContent;
        private ScrollViewer _scrollViewer;
        #endregion

        #region Property

        /// <summary>
        /// The threshold for release to refresh,defautl value is 2/5 of PullToRefreshPanel's height.
        /// </summary>
        public double RefreshThreshold
        {
            get { return (double)GetValue(RefreshThresholdProperty); }
            set { SetValue(RefreshThresholdProperty, value); }
        }

        // Using a DependencyProperty as the backing store for RefreshThreshold.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty RefreshThresholdProperty =
            DependencyProperty.Register("RefreshThreshold", typeof(double), typeof(PullToRefreshControl), new PropertyMetadata(0.0,new PropertyChangedCallback(OnRefreshThresholdChanged)));

        private static void OnRefreshThresholdChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var pullToRefreshControl = d as PullToRefreshControl;
            pullToRefreshControl.UpdateContentGrid();
        }

        /// <summary>
        /// occur when reach threshold.
        /// </summary>
        public event EventHandler PullToRefresh;

        public DataTemplate HeaderTemplate
        {
            get { return (DataTemplate)GetValue(HeaderTemplateProperty); }
            set { SetValue(HeaderTemplateProperty, value); }
        }

        // Using a DependencyProperty as the backing store for HeaderTemplate.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty HeaderTemplateProperty =
            DependencyProperty.Register("HeaderTemplate", typeof(DataTemplate), typeof(PullToRefreshControl), new PropertyMetadata(null));

        public bool IsReachThreshold    
        {
            get { return (bool)GetValue(IsReachThresholdProperty); }
            set { SetValue(IsReachThresholdProperty, value); }
        }

        // Using a DependencyProperty as the backing store for IsReachThreshold.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty IsReachThresholdProperty =
            DependencyProperty.Register("IsReachThreshold", typeof(bool), typeof(PullToRefreshControl), new PropertyMetadata(false));


        #endregion

        protected override void OnApplyTemplate()
        {
            _panelHeader = GetTemplateChild(PanelHeader) as ContentControl;
            _panelHeader.DataContext = this;
            _panelContent = GetTemplateChild(PanelContent) as ContentPresenter;
            _scrollViewer = GetTemplateChild(ScrollViewer) as ScrollViewer;
            _scrollViewer.ViewChanged += _scrollViewer_ViewChanged;
            base.OnApplyTemplate();
        }

        private void _scrollViewer_ViewChanged(object sender, ScrollViewerViewChangedEventArgs e)
        {
            //Sometime we can't make it to 0.0.
            IsReachThreshold = _scrollViewer.VerticalOffset <= 5.0;
            if (e.IsIntermediate)
            {
                return;
            }

            if (IsReachThreshold)
            {
                if (PullToRefresh!=null)
                {
                    PullToRefresh(this, null);
                }
            }
            _panelHeader.Height = RefreshThreshold > _panelHeader.ActualHeight ? RefreshThreshold : _panelHeader.ActualHeight;
            this.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
            {
                _scrollViewer.ChangeView(null, _panelHeader.Height, null);
            });

        }

        public PullToRefreshControl()
        {
            this.DefaultStyleKey = typeof(PullToRefreshControl);
            this.Loaded +=(s,e)=>
            {
                if (RefreshThreshold == 0.0)
                {
                    RefreshThreshold = this.ActualHeight * 2 / 5.0;
                }
                UpdateContentGrid();
            };
            this.SizeChanged += (s, e) =>
            {
                if (RefreshThreshold==0.0)
                {
                    RefreshThreshold = this.ActualHeight *2 / 5.0;
                }
                UpdateContentGrid();
            };
        }

        #region Method
        private void UpdateContentGrid()
        {
            if (_scrollViewer != null && _panelContent!=null && _panelHeader !=null)
            {
                _panelHeader.Height = RefreshThreshold > _panelHeader.ActualHeight? RefreshThreshold: _panelHeader.ActualHeight;
                this.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
                {
                    _scrollViewer.ChangeView(null, _panelHeader.Height, null, true);
                });
                _panelContent.Width = this.ActualWidth;
                _panelContent.Height = this.ActualHeight;
            }
        }
        #endregion
    }

 

目录
相关文章
|
C# Windows
WPF技术之ToolBar控件
WPF ToolBar控件是Windows Presentation Foundation(WPF)中的一个常用工具栏控件,它可以用于在应用程序中显示一组工具按钮或命令按钮。ToolBar可以被嵌套在其他控件内部,例如窗口或面板,并支持自定义布局。
417 0
|
XML 编解码 数据可视化
第三讲 UI控件使用
第三讲 UI控件使用
180 0
第三讲 UI控件使用
|
C#
【WPF】使用Popup控件做浮窗/提示框
原文:【WPF】使用Popup控件做浮窗/提示框 需求:当鼠标移入某个区域时,弹出一个浮窗,以便用户进行下一步操作。 效果如下图: 当鼠标移入左上角的【多选显示】框内,出现下面的浮窗(悬浮在原UI之上)。
4431 0
|
容器 网络架构 C#
WPF 控件库——可拖动选项卡的TabControl
原文:WPF 控件库——可拖动选项卡的TabControl 一、先看看效果   二、原理 1、选项卡大小和位置   这次给大家介绍的控件是比较常用的TabControl,网上常见的TabControl样式有很多,其中一部分也支持拖动选项卡,但是带动画效果的很少见。
1620 0
|
API iOS开发 UED
iOS集成下拉刷新控件 & 实现无感知上拉加载更多
iOS集成下拉刷新控件 & 实现无感知上拉加载更多
318 0
iOS集成下拉刷新控件 & 实现无感知上拉加载更多
|
Android开发 iOS开发 索引
Xamarin自定义布局系列——支持无限滚动的自动轮播视图CarouselView
原文:Xamarin自定义布局系列——支持无限滚动的自动轮播视图CarouselView 背景简述 自动轮播视图(CarouselView)在现在App中的地位不言而喻,绝大多数的App中都有类似的视图,无论是WebApp还是Native App。
1884 0
|
C# 开发者
[UWP]新控件ColorPicker
原文:[UWP]新控件ColorPicker 1. 前言 Fall Creators Update中提供了一个新得ColorPicker控件,解决了以前选择颜色只能用Combo Box的窘境。 2. 一个简单的例子 如上所示,ColorPiker可以通过在光谱或色轮上拖动滑块,或者在RGB/HSV及十六进制的TextBox中直接输入颜色的数值改变Color属性。
1047 0
|
C# Windows
在VS2005中设置WPF中自定义按钮的事件
原文:在VS2005中设置WPF中自定义按钮的事件 上篇讲了如何在Blend中绘制圆角矩形(http://blog.csdn.net/johnsuna/archive/2007/08/13/1740781.aspx),本篇继续下一步骤,如何自定义按钮的事件。
1050 0
|
C# Windows
WPF实现炫酷Loading控件
原文:WPF实现炫酷Loading控件 Win8系统的Loading效果还是很不错的,网上也有人用CSS3等技术实现,研究了一下,并打算用WPF自定义一个Loading控件实现类似的效果,并可以让用户对Loading的颗粒(Particle)背景颜色进行自定义,话不多说,直接上代码: 1、用VS2...
1270 0
|
C#
WPF 控件库——轮播控件
原文:WPF 控件库——轮播控件 一、要做成什么样   bs端的轮播控件千千万,有的甚至能作为一个单独的库来开发,所涉及到的功能也是缤纷多彩。相对来说,cs端的轮播用得不多,我这里只是简单的做了个能满足一般需求的轮播,在项目中凑会凑会还是可以的。
1900 0