在手机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 > )
{
DependencyObject current = queue.Dequeue();
for (int i = VisualTreeHelper.GetChildrenCount(current) - ; <= 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(); App.Current.Dispatcher.BeginInvoke(new Action(()=> { AddMoreItems(); Busy = false; }));
});
});
} private void AddMoreItems()
{
int start = items.Count;
int end = start + ;
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下拉显示更多内容的更多相关文章

  1. wpf mvvm模式下CommandParameter传递多参

    原文:wpf mvvm模式下CommandParameter传递多参 CommandParameter一般只允许设置一次,所以如果要传递多参数,就要稍微处理一下.我暂时还没找到更好的方案,下面介绍的这 ...

  2. WPF MVVM模式的一些理解

    /*本文转自 http://www.cnblogs.com/sirkevin/archive/2012/11/28/2793471.html */ 使用WPF+Mvvm开发一年多,期间由于对Mvvm模 ...

  3. WPF自学入门(十一)WPF MVVM模式Command命令 WPF自学入门(十)WPF MVVM简单介绍

    WPF自学入门(十一)WPF MVVM模式Command命令   在WPF自学入门(十)WPF MVVM简单介绍中的示例似乎运行起来没有什么问题,也可以进行更新.但是这并不是我们使用MVVM的正确方式 ...

  4. WPF MVVM模式中,通过命令实现窗体拖动、跳转以及显隐控制

    原文:WPF MVVM模式中,通过命令实现窗体拖动.跳转以及显隐控制 在WPF中使用MVVM模式,可以让我们的程序实现界面与功能的分离,方便开发,易于维护.但是,很多初学者会在使用MVVM的过程中遇到 ...

  5. 解决boostrap中,iframe渲染下,苹果手机横向无法显示剩余内容问题

    描述: 问题解决了,采用的手势拖动显示剩余内容,并不是有了横向滚动条 在head标签中加入 <head> <meta charset="utf-8"> &l ...

  6. [WPF疑难] 模式窗口被隐藏后重新显示时变成了非模式窗口

    原文:[WPF疑难] 模式窗口被隐藏后重新显示时变成了非模式窗口 [WPF疑难] 模式窗口被隐藏后重新显示时变成了非模式窗口 周银辉 现象: 大家可以试试下面这个很有趣但会带来Defect的现象:当我 ...

  7. WPF MVVM模式下的无阻塞刷新探讨

    很多时候我们需要做一个工作,在一个方法体里面,读取大数据绑定到UI界面,由于长时间的读取,读取独占了线程域,导致界面一直处于假死状态.例如,当应用程序开始读取Web资源时,读取的时效是由网络链路的速度 ...

  8. WPF MVVM模式下ComboBox级联效果 选择第一项

    MVVM模式下做的省市区的级联效果.通过改变ComboBox执行命令改变市,区. 解决主要问题就是默认选中第一项 1.首先要定义一个属性,继承自INotifyPropertyChanged接口.我这里 ...

  9. WPF自学入门(十一)WPF MVVM模式Command命令

    在WPF自学入门(十)WPF MVVM简单介绍中的示例似乎运行起来没有什么问题,也可以进行更新.但是这并不是我们使用MVVM的正确方式.正如上一篇文章中在开始说的,MVVM的目的是为了最大限度地降低了 ...

随机推荐

  1. redis安装与参数说明

    redis安装与参数说明 博客分类: redis redis 1.下载tcl8.6.1-src.tar.gz 和 redis-2.8.6.tar.gz: 2.安装: 1).安装tcl Java代码 收 ...

  2. iOS学习之UINavigationController详解与使用(一)添加UIBarButtonItem

    http://blog.csdn.net/totogo2010/article/details/7681879 1.UINavigationController导航控制器如何使用 UINavigati ...

  3. 【leetcode】Next Permutation

    Next Permutation Implement next permutation, which rearranges numbers into the lexicographically nex ...

  4. 在中文windows下使用pywinauto进行窗口操作

    这两天开始接触pywinauto,听说百度的自动化QA也用这个模块,于是来了兴趣,但网上的教程很少,而且基本上都是拿官方的notepad来说,首先中文菜单的支持是问题,其次各种操作也没有写清楚,阅读官 ...

  5. C++实现VPN工具之VPN错误代码大全

    该篇文章转自:<VPN问题全攻略>http://home.51.com/h012359/diary/item/10008457.html 以下是使用VPN版软件中常见的一些错误代码: 1. ...

  6. 括号配对问题_栈<stack>

    问题 A: 括号配对问题 时间限制: 3 Sec  内存限制: 128 MB提交: 3  解决: 2[提交][状态][讨论版] 题目描述 现在,有一行括号序列,请你检查这行括号是否配对. 输入 第一行 ...

  7. 谷歌 Uncaught SecurityError: Failed to execute 'replaceState' on 'History 错误

    今天在用sui mobil做一个内联页面的时候遇到了这个问题. 然而这个问题只出现在chrome浏览器中,在火狐中没有一点问题. 他说明的是一个安全问题,chrome中有了新的安全机制

  8. String.prototype.substr()

    概述 substr() 方法返回字符串中从指定位置开始到指定长度的子字符串. 语法 str.substr(start[, length]) 参数 start 开始提取字符的位置.如果为负值,则被看作  ...

  9. 用window.print()打印指定div里面的内容(转载的)

    用window.print()打印指定div里面的内容 今天客户让添加个打印证照功能,直接用window.print()打印的是整个页面,而用以下方法就可以只打印证明了 <!--window.p ...

  10. 【python】Head First Python(五)

    无聊,看看<Head First Python>打发一下时间.感觉这本书很一般,可以无聊的时候翻翻.每一章页数很多,但都没讲什么东西. 先看第五章.记录一下知识点: f.readline( ...