在手机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. struts2 配置 struts.xml 提示

    1.这个提示通常是在 连网络的时候才可以看到 2.当没有网路的时候我们该如何配置呢? window -->preferences -->xml catelog -->user.... ...

  2. java.lang.UnsatisfiedLinkError: Couldn't load hyphenate_av from loader dalvik.system.PathClassLoader

    android studio引入第三方库时报如下异常. 06-15 16:50:24.477 9497-9497/easemobim.test.com.easemobim E/AndroidRunti ...

  3. div加jquery实现iframe标签的功能

    由于最近项目需要,前端后台都完全采用div+css的方式布局.因而左思右想,有什么办法可以替代常用的iframe上下左右的布局方式,而且页面只是局部刷新.参考了许多前辈的资料,并加以整理,因而有了以下 ...

  4. ios 中的autoresizingMask

    以前对这个知识理解的不太对,看了下面这个地址的文章后,感觉说的对,也没检验,今天实验后,发现是错的...在这里对以前读过此文的朋友表示抱歉. 原文地址如下: http://www.cnblogs.co ...

  5. nginx服务器绑定域名和设置根目录的方法

    nginx服务器绑定域名以及设置根目录非常方便,首先进入nginx安装目录,然后执行 vim conf/nginx.conf 打开nginx的配置文件,找到 server { ..... ..... ...

  6. 内存管理_JAVA内存管理

    Java虚拟机规范中试图定义一种Java内存模型(Java Memory Model,JMM)来屏蔽各个硬件平台和操作系统的内存访问差异,以实现让Java程序在各种平台下都能达到一致的内存访问效果.那 ...

  7. metro中stream转IRandomAccessStream

    下面的例子是从zip压缩文件解压出jpg文件流,再显示出来. StorageFile zip = await KnownFolders.PicturesLibrary.GetFileAsync(&qu ...

  8. Android屏幕适配dp、px两套解决办法

    "又是屏幕适配,这类文章网上不是很多了吗?" 我也很遗憾,确实又是老问题.但本文重点对网上的各种方案做一个简短的总结,和具体使用方法. 若想了解具体Android设备适配的前世因果 ...

  9. 【leetcode】Candy(hard) 自己做出来了 但别人的更好

    There are N children standing in a line. Each child is assigned a rating value. You are giving candi ...

  10. ssh自动登陆

    突然碰到有人问ssh再传输密钥时候能不手动输入密码,由于没有碰到过这种情况,所以查了一下发现可以用sshpass做到. sshpass [参数] ssh命令: 参数: -p password  #将参 ...