WPF MVVM模式下实现ListView下拉显示更多内容
在手机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下拉显示更多内容的更多相关文章
- wpf mvvm模式下CommandParameter传递多参
原文:wpf mvvm模式下CommandParameter传递多参 CommandParameter一般只允许设置一次,所以如果要传递多参数,就要稍微处理一下.我暂时还没找到更好的方案,下面介绍的这 ...
- WPF MVVM模式的一些理解
/*本文转自 http://www.cnblogs.com/sirkevin/archive/2012/11/28/2793471.html */ 使用WPF+Mvvm开发一年多,期间由于对Mvvm模 ...
- WPF自学入门(十一)WPF MVVM模式Command命令 WPF自学入门(十)WPF MVVM简单介绍
WPF自学入门(十一)WPF MVVM模式Command命令 在WPF自学入门(十)WPF MVVM简单介绍中的示例似乎运行起来没有什么问题,也可以进行更新.但是这并不是我们使用MVVM的正确方式 ...
- WPF MVVM模式中,通过命令实现窗体拖动、跳转以及显隐控制
原文:WPF MVVM模式中,通过命令实现窗体拖动.跳转以及显隐控制 在WPF中使用MVVM模式,可以让我们的程序实现界面与功能的分离,方便开发,易于维护.但是,很多初学者会在使用MVVM的过程中遇到 ...
- 解决boostrap中,iframe渲染下,苹果手机横向无法显示剩余内容问题
描述: 问题解决了,采用的手势拖动显示剩余内容,并不是有了横向滚动条 在head标签中加入 <head> <meta charset="utf-8"> &l ...
- [WPF疑难] 模式窗口被隐藏后重新显示时变成了非模式窗口
原文:[WPF疑难] 模式窗口被隐藏后重新显示时变成了非模式窗口 [WPF疑难] 模式窗口被隐藏后重新显示时变成了非模式窗口 周银辉 现象: 大家可以试试下面这个很有趣但会带来Defect的现象:当我 ...
- WPF MVVM模式下的无阻塞刷新探讨
很多时候我们需要做一个工作,在一个方法体里面,读取大数据绑定到UI界面,由于长时间的读取,读取独占了线程域,导致界面一直处于假死状态.例如,当应用程序开始读取Web资源时,读取的时效是由网络链路的速度 ...
- WPF MVVM模式下ComboBox级联效果 选择第一项
MVVM模式下做的省市区的级联效果.通过改变ComboBox执行命令改变市,区. 解决主要问题就是默认选中第一项 1.首先要定义一个属性,继承自INotifyPropertyChanged接口.我这里 ...
- WPF自学入门(十一)WPF MVVM模式Command命令
在WPF自学入门(十)WPF MVVM简单介绍中的示例似乎运行起来没有什么问题,也可以进行更新.但是这并不是我们使用MVVM的正确方式.正如上一篇文章中在开始说的,MVVM的目的是为了最大限度地降低了 ...
随机推荐
- ndk学习7: 使用静态库
目录: 手工编译静态库 ndk-build编译静态库 手工编译静态库 老规矩还是先手工操作,知其然并知其所以然 需要用到的核心命令: gcc –g –c mod1.c mod2.c mod3. ...
- python查找并删除相同文件-UNIQ File-wxPython-v6
相比第一版,新增:菜单,对话框,文件过滤器,操作结果保存,配置功能(自己写了一个读写配置文件的功能),提示语优化,模块分化更合理. 截图: 源代码: UniqFile-wxPython-v6.py: ...
- ubuntu update dns server
edit: /etc/resolvconf/resolv.conf.d/base nameserver 114.114.114.114 execute this: $ resolvconf -u f ...
- Android Studio (Gradle)编译错误
Error:Execution failed for task ':app:processDebugResources' .com.android.ide.common.process.Process ...
- jenkins gitlab整合注意事项
jenkins整合gitlab时,Source Code Management添加gitlab仓库路径无论怎么尝试都报如下两个异常: Failed to connect to repository : ...
- FastReport调用Delphi中的自定义函数(人民币大写金额)mtm
1. 在 FormCreate 中向FastReprot添加函数 (fPrint)窗口 procedure TfPrint.FormCreate(Sender: TObject); frxReport ...
- Java Thread.join()方法
一.使用方式. join是Thread类的一个方法,启动线程后直接调用,例如: Thread t = new AThread(); t.start(); t.join(); 二.为什么要用join() ...
- Java for LeetCode 218 The Skyline Problem【HARD】
A city's skyline is the outer contour of the silhouette formed by all the buildings in that city whe ...
- AIX系统的环境变量设置
AIX系统的环境变量设置 用户环境的定义是通过设置环境变量来实现的.AIX系统主要使用两大类profile文件来定义用户环境.一类是用来为所有用户定制环境,另一类是为个人定义自己的环境. 登录时,sh ...
- App主界面Tab实现方法
ViewPager + FragmentPagerAdapter 这里模仿下微信APP界面的实现 国际惯例,先看下效果图: activity_main.xml 布局文件: <?xml ver ...