Search code examples
c#windows-phone-8converterslonglistselector

Determine when LongListSelector is Scrolling


I would just simply like to be able to minimize the application bar when I am scrolling down, and then show its normal size when scrolling up. I've seen this ability on the facebook app and it seems very appealing and user friendly. I have my LongListSelector with items bound to it, and an appbar already in code behind. What is the missing key to enable such a feature?


Solution

  • You just need to figure out when the user is scrolling and in what direction. Here's a great article with example code. Detecting WP8 LongListSelector’s end of scroll. You can modify it to the point where it does exactly what you want.

    However, if I was going do it, I would take a more direct route. I would derived my own LLS and attach a property to the value of the scrollbar. Something like this :)

    public class MyLLS : LongListSelector, INotifyPropertyChanged
    {
        // implement the INotify
        public event PropertyChangedEventHandler PropertyChanged;
        private void NotifyPropertyChanged(String propertyName)
        {            
            PropertyChangedEventHandler handler = PropertyChanged;
            if (null != handler)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    
        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
    
            // dat grab doe
            sb = this.GetTemplateChild("VerticalScrollBar") as System.Windows.Controls.Primitives.ScrollBar;
            sb.ValueChanged += sb_ValueChanged;           
        }
    
        void sb_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            // an animation has happen and they have moved a significance distance
            // set the new value
            ScrollValue = e.NewValue;
    
            // determine scroll direction
            if(e.NewValue > e.OldValue)
            {
                scroll_direction_down = true;
            }
            else
            {
                scroll_direction_down = false;
            }
        }
    
        public System.Windows.Controls.Primitives.ScrollBar sb;
    
        private bool scroll_direction_down = false;   // or whatever default you want
    
        public bool ScrollDirectionDown
        { get { return scroll_direction_down; } }
    
        public double ScrollValue
        {
            get
            {
                if (sb != null)
                {
                    return sb.Value;
                }
                else
                    return 0;
            }
            set
            {
                sb.Value = value;
                NotifyPropertyChanged("ScrollValue");
            }
        }
    }
    

    Now you know the exact scroll position. You can even get the top and bottom value by doing

    double min = this.sb.Minimum;
    double max = this.sb.Maximum;
    

    Now bind that ScrollDirectionDown property to a converter to your AppBar visibility and you'll have your goals met.


    If you can't bind then you have to do a callback to update the visibility. But if you want something more simple just hook it up to the ManipulationStateChanged event of the custom LLS.

    public partial class MainPage : PhoneApplicationPage
    {
        // Constructor
        public MainPage()
        {
            InitializeComponent();
        } 
    
        private void lls_ManipulationStateChanged(object sender, EventArgs e)
        {
            if (lls.ScrollDirectionDown)
            {
                ApplicationBar.IsVisible = false;
            }
            else
            {
                ApplicationBar.IsVisible = true;
            }             
        }
    }