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
    }

 

目录
相关文章
|
8月前
|
C# 容器
WPF技术之StatusBar控件
WPF StatusBar控件用于在应用程序底部显示状态信息。它提供了一个容器,用于展示与应用程序相关的各种状态信息。
446 0
|
XML 编解码 数据可视化
第三讲 UI控件使用
第三讲 UI控件使用
146 0
第三讲 UI控件使用
|
C#
【WPF】使用Popup控件做浮窗/提示框
原文:【WPF】使用Popup控件做浮窗/提示框 需求:当鼠标移入某个区域时,弹出一个浮窗,以便用户进行下一步操作。 效果如下图: 当鼠标移入左上角的【多选显示】框内,出现下面的浮窗(悬浮在原UI之上)。
4191 0
|
API iOS开发 UED
iOS集成下拉刷新控件 & 实现无感知上拉加载更多
iOS集成下拉刷新控件 & 实现无感知上拉加载更多
278 0
iOS集成下拉刷新控件 & 实现无感知上拉加载更多
|
C# 开发者
[UWP]新控件ColorPicker
原文:[UWP]新控件ColorPicker 1. 前言 Fall Creators Update中提供了一个新得ColorPicker控件,解决了以前选择颜色只能用Combo Box的窘境。 2. 一个简单的例子 如上所示,ColorPiker可以通过在光谱或色轮上拖动滑块,或者在RGB/HSV及十六进制的TextBox中直接输入颜色的数值改变Color属性。
1018 0
|
C# Windows
WPF实现炫酷Loading控件
原文:WPF实现炫酷Loading控件 Win8系统的Loading效果还是很不错的,网上也有人用CSS3等技术实现,研究了一下,并打算用WPF自定义一个Loading控件实现类似的效果,并可以让用户对Loading的颗粒(Particle)背景颜色进行自定义,话不多说,直接上代码: 1、用VS2...
1239 0
|
C#
WPF 控件库——轮播控件
原文:WPF 控件库——轮播控件 一、要做成什么样   bs端的轮播控件千千万,有的甚至能作为一个单独的库来开发,所涉及到的功能也是缤纷多彩。相对来说,cs端的轮播用得不多,我这里只是简单的做了个能满足一般需求的轮播,在项目中凑会凑会还是可以的。
1801 0
|
存储 前端开发 C#
WPF自定义控件第一 - 进度条控件
原文:WPF自定义控件第一 - 进度条控件 本文主要针对WPF新手,高手可以直接忽略,更希望高手们能给出一些更好的实现思路。 前期一个小任务需要实现一个类似含步骤进度条的控件。虽然对于XAML的了解还不是足够深入,还是摸索着做了一个。
1176 0
|
C#
WPF中Popup等弹窗的位置不对(偏左或者偏右)
原文:WPF中Popup等弹窗的位置不对(偏左或者偏右) 1.情况如图:    正常情况:         部分特殊情况:        在一般的电脑都能正确显示,就是第一种情况,同样的代码为什么在不同的电脑就会显示不同的位置呢,原来Windows为了满足 不同需求的用户,左撇子和右撇子,就...
1804 0