WPF MVVM模式下實現ListView下拉顯示更多內容

來源:互聯網
上載者:User

標籤:

在手機App中,如果有一個展示資訊的列表,通常會展示很少一部分,當使用者滑動到列表底部時,再載入更多內容。這樣有兩個好處,提高程式效能,減少網路流量。這篇部落格中,將介紹如何在WPF ListView中實現這個功能。

實現思路:為ListView新增一個附加屬性,用來綁定當下拉到底部時觸發增加列表內容的功能。

XAML:

    <Window.Resources>        <BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>    </Window.Resources>    <Grid>        <ListView ItemsSource="{Binding Items}" Height="150" Width="80" local:ScrollViewerMonitor.AtEndCommand="{Binding FetchMoreDataCommand}">            <ListView.ItemTemplate>                <DataTemplate>                    <StackPanel Orientation="Horizontal">                        <TextBlock Text="{Binding}"/>                    </StackPanel>                </DataTemplate>            </ListView.ItemTemplate>        </ListView>        <UserControl Opacity=".85" Background="Gray" Height="150" Width="80" Visibility="{Binding Busy, Converter={StaticResource BooleanToVisibilityConverter}}">            <TextBlock Text="Loading..." Foreground="White" HorizontalAlignment="Center" VerticalAlignment="Center"/>        </UserControl>    </Grid>

ScrollViewerMonitor:

public class ScrollViewerMonitor    {        public static ICommand GetAtEndCommand(DependencyObject obj)        {            return (ICommand)obj.GetValue(AtEndCommandProperty);        }        public static void SetAtEndCommand(DependencyObject obj, ICommand value)        {            obj.SetValue(AtEndCommandProperty, value);        }        public static readonly DependencyProperty AtEndCommandProperty =            DependencyProperty.RegisterAttached("AtEndCommand", typeof(ICommand),                 typeof(ScrollViewerMonitor), new PropertyMetadata(OnAtEndCommandChanged));        public static void OnAtEndCommandChanged(            DependencyObject d, DependencyPropertyChangedEventArgs e)        {            FrameworkElement element = (FrameworkElement)d;            if (element != null)            {                element.Loaded -= element_Loaded;                element.Loaded += element_Loaded;            }        }        private static void element_Loaded(object sender, RoutedEventArgs e)        {            FrameworkElement element = (FrameworkElement)sender;            element.Loaded -= element_Loaded;            ScrollViewer scrollViewer = FindChildOfType<ScrollViewer>(element);            if(scrollViewer == null)            {                throw new InvalidOperationException("ScrollViewer not found.");            }            scrollViewer.ScrollChanged += delegate             {                bool atBottom = scrollViewer.VerticalOffset                                  >= scrollViewer.ScrollableHeight;                if(atBottom)                {                    var atEnd = GetAtEndCommand(element);                    if(atEnd != null)                    {                        atEnd.Execute(null);                    }                }            };        }        private static T FindChildOfType<T>(DependencyObject root) where T : class        {            var queue = new Queue<DependencyObject>();            queue.Enqueue(root);            while (queue.Count > 0)            {                DependencyObject current = queue.Dequeue();                for (int i = VisualTreeHelper.GetChildrenCount(current) - 1; 0 <= i; i--)                {                    var child = VisualTreeHelper.GetChild(current, i);                    var typedChild = child as T;                    if (typedChild != null)                    {                        return typedChild;                    }                    queue.Enqueue(child);                }            }            return null;        }    }

MainViewModel:

public class MainViewModel : INotifyPropertyChanged    {        public MainViewModel()        {            _busy = false;            AddMoreItems();            fetchMoreDataCommand = new DelegateCommand(() => {                ThreadPool.QueueUserWorkItem(                    delegate                    {                        Busy = true;                        Thread.Sleep(3000);                        App.Current.Dispatcher.BeginInvoke(new Action(()=> {                            AddMoreItems();                            Busy = false;                        }));                    });            });        }        private void AddMoreItems()        {            int start = items.Count;            int end = start + 10;            for (int i = start; i < end; i++)            {                items.Add("Item " + i);            }        }        readonly DelegateCommand fetchMoreDataCommand;        public ICommand FetchMoreDataCommand        {            get            {                return fetchMoreDataCommand;            }        }        private ObservableCollection<string> items = new ObservableCollection<string>();        public ObservableCollection<string> Items        {            get            {                return items;            }        }        private bool _busy;        public bool Busy        {            get            {                return _busy;            }            set            {                if(_busy != value)                {                    _busy = value;                    OnPropertyChanged("Busy");                }            }        }        public event PropertyChangedEventHandler PropertyChanged;        protected virtual void OnPropertyChanged(string propertyName)        {            if(PropertyChanged != null)            {                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));            }        }    }

Busy屬性用來決定是否顯示Loading。

運行效果:

感謝您的閱讀!代碼點擊這裡下載。

WPF MVVM模式下實現ListView下拉顯示更多內容

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.