(1)、效果描述:
原始数据数为100项, 每次加载8项
当已显示的加载项数为100时和原始数据项数小于8项时,Button隐藏掉,其他情况显示Button
(2)、实现思路
a、ListBox数据源
原始数据源和ListBox实际绑定数据源分开,实际数据源第一次加载8项,之后每次在其基础上追加8项。
b、UI效果
把ListBox和Button使用ScrollViewer包起来,这样看起来Button就像是ListBox的最后一项Item,当然要把ListBox里的纵向滚动条设置为Disabled。
c、Button的动态显示
Button的显示与否是有 原始数据项数 和 当前实际绑定数据源项数决定的;
因此我们可以设计一个值转换器来完成这个效果,在这里我们通过一个封装的类MoreButonVis(我这里定义为MoreButonVis)来包含 原始数据源项数 和 当前实际数据源项数,在这里进行判断处理。
(3)、实现过程中遇到的小麻烦
描述:由于我是将ListBox原始数据源和MoreButonVis类 封装到一个LstBoxModel类中,当我们改变LstBoxModel类中的MoreButonVis类里面属性值时,UI页面并没有收到改变通知,所以呢这个“加载更多”按钮会一直显示。
解决方法:我们可以设置一个delegate,在MoreButonVis类中加入delegate成员变量, 而在LstBoxModel中为MoreButonVis中的delegate注册处理方法,也就是通知页面UI MoreButonVis 发生改变。
(4)、主要代码片段:
a、数据源定义 SimpleModel、MoreButonVis 和 LstBoxModel

1 using System; 2 using System.ComponentModel; 3 4 namespace LoadingDataDemo 5 { 6 public class SimpleModel : INotifyPropertyChanged 7 { 8 /// <summary> 9 /// name or title 10 /// </summary> 11 protected string SelfName = string.Empty; 12 public string Name 13 { 14 get { return SelfName; } 15 set 16 { 17 SelfName = value; 18 NotifyPropertyChanged("Name"); 19 } 20 } 21 22 /// <summary> 23 /// fuction description 24 /// </summary> 25 protected string SelfDescription = string.Empty; 26 public string Discription 27 { 28 get { return SelfDescription; } 29 set 30 { 31 SelfDescription = value; 32 NotifyPropertyChanged("Discription"); 33 } 34 } 35 36 public event PropertyChangedEventHandler PropertyChanged; 37 protected void NotifyPropertyChanged(string propertyName) 38 { 39 if (PropertyChanged != null) 40 { 41 PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 42 } 43 } 44 } 45 }

1 public class MoreButonVis : INotifyPropertyChanged 2 { 3 public NotifyPanlChanged NofityChangedPanl; 4 5 #region attribute 6 7 private int SelfAppLstModelCount = 0; 8 public int AppLstModelCount 9 { 10 get { return SelfAppLstModelCount; } 11 set 12 { 13 if (SelfAppLstModelCount != value) 14 { 15 SelfAppLstModelCount = value; 16 if (NofityChangedPanl != null) 17 NofityChangedPanl(); 18 NotifyPropertyChanged("AppLstModelCount"); 19 } 20 } 21 } 22 23 private int SelfPageLstModelCount = 0; 24 public int PageLstModelCount //是个索引值 25 { 26 get { return SelfPageLstModelCount; } 27 set 28 { 29 if (SelfPageLstModelCount != value) 30 { 31 SelfPageLstModelCount = value; 32 if (NofityChangedPanl != null) 33 NofityChangedPanl(); 34 NotifyPropertyChanged("PageLstModelCount"); 35 } 36 } 37 } 38 39 #endregion //attribute 40 41 #region overwritten INotifyPropertyChanged 42 43 public event PropertyChangedEventHandler PropertyChanged; 44 protected void NotifyPropertyChanged(string propertyName) 45 { 46 if (PropertyChanged != null) 47 { 48 PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 49 } 50 } 51 52 #endregion //INotifyPropertyChanged 53 }

1 public class LstBoxModel : INotifyPropertyChanged, INotifyCollectionChanged 2 { 3 public LstBoxModel() 4 { 5 SelfMore = new MoreButonVis(); 6 SelfMore.PropertyChanged += new PropertyChangedEventHandler(SelfMore_PropertyChanged); 7 SelfLstModel = new ObservableCollection<SimpleModel>(); 8 } 9 10 void SelfMore_PropertyChanged(object sender, PropertyChangedEventArgs e) 11 { 12 NotifyPropertyChanged("More"); 13 } 14 15 #region attribute 16 17 /// <summary> 18 /// whether or not the data is loaded 19 /// </summary> 20 public bool IsDataLoaded { get; private set; } 21 22 /// <summary> 23 /// ListBox's Itemsource 24 /// </summary> 25 private ObservableCollection<SimpleModel> SelfLstModel = null; 26 public ObservableCollection<SimpleModel> LstModel 27 { 28 get 29 { 30 if (SelfLstModel != null) 31 More.AppLstModelCount = SelfLstModel.Count; 32 return SelfLstModel; 33 } 34 set 35 { 36 SelfLstModel = value; 37 NotifyPropertyChanged("LstModel"); 38 } 39 } 40 41 /// <summary> 42 /// The more Button show 43 /// </summary> 44 private MoreButonVis SelfMore = null; 45 public MoreButonVis More 46 { 47 get { return SelfMore; } 48 set 49 { 50 SelfMore = value; 51 NotifyPropertyChanged("More"); 52 } 53 } 54 55 #endregion //attribute 56 57 #region overwritten INotifyPropertyChanged 58 59 public event PropertyChangedEventHandler PropertyChanged; 60 protected void NotifyPropertyChanged(string propertyName) 61 { 62 if (PropertyChanged != null) 63 { 64 PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 65 } 66 } 67 68 public event NotifyCollectionChangedEventHandler CollectionChanged; 69 protected void NotifyCollectionChanged(string collectionName) 70 { 71 if (CollectionChanged != null) 72 { 73 CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace)); 74 } 75 } 76 77 #endregion //INotifyPropertyChanged 78 79 /// <summary> 80 /// Load data 81 /// </summary> 82 public void LoadData() 83 { 84 for (int i = 0; i < 100; i++) 85 { 86 LstModel.Add(new SimpleModel() { Name = "第" + i + "项", Discription = "这是第" + i + "项数据" }); 87 } 88 89 IsDataLoaded = true; 90 } 91 }
b、delegate定义
public delegate void NotifyPanlChanged();
c、值转换器定义

1 public class NumToButonVis : IValueConverter 2 { 3 public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 4 { 5 if (value is MoreButonVis) 6 { 7 if (((MoreButonVis)value).AppLstModelCount > 8 8 && ((MoreButonVis)value).PageLstModelCount < ((MoreButonVis)value).AppLstModelCount -1) 9 return Visibility.Visible; 10 else 11 return Visibility.Collapsed; 12 } 13 else 14 return null; 15 } 16 public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 17 { 18 return null; 19 } 20 }
d、UI xaml

1 <phone:PhoneApplicationPage 2 x:Class="LoadingDataDemo.MainPage" 3 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 4 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 5 xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone" 6 xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone" 7 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 8 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 9 mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="696" 10 FontFamily="{StaticResource PhoneFontFamilyNormal}" 11 FontSize="{StaticResource PhoneFontSizeNormal}" 12 Foreground="{StaticResource PhoneForegroundBrush}" 13 SupportedOrientations="Portrait" Orientation="Portrait" 14 shell:SystemTray.IsVisible="True" xmlns:locat="clr-namespace:LoadingDataDemo" 15 d:DataContext="{d:DesignData Design/SampleDataDesign.xaml}"> 16 17 <phone:PhoneApplicationPage.Resources> 18 <ResourceDictionary> 19 <locat:NumToButonVis x:Key="NumToButonVis1" /> 20 </ResourceDictionary> 21 </phone:PhoneApplicationPage.Resources> 22 23 <!--Sample code showing usage of ApplicationBar--> 24 <phone:PhoneApplicationPage.ApplicationBar> 25 <shell:ApplicationBar IsVisible="True" IsMenuEnabled="True"> 26 <shell:ApplicationBarIconButton IconUri="/Images/icon_delete.png" Text="删除" Click="ApplicationBarIconButton_Click"/> 27 <shell:ApplicationBarIconButton IconUri="/Images/icon_choose.png" Text="全选" Click="ApplicationBarIconButton_Click_1"/> 28 </shell:ApplicationBar> 29 </phone:PhoneApplicationPage.ApplicationBar> 30 31 <!--LayoutRoot is the root grid where all page content is placed--> 32 <Grid x:Name="LayoutRoot" Background="Transparent"> 33 <Grid.RowDefinitions> 34 <RowDefinition Height="Auto"/> 35 <RowDefinition Height="*"/> 36 </Grid.RowDefinitions> 37 38 <!--TitlePanel contains the name of the application and page title--> 39 <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28"> 40 <TextBlock x:Name="ApplicationTitle" Text="LOADING DATA TEST" Style="{StaticResource PhoneTextNormalStyle}"/> 41 </StackPanel> 42 43 <!--ContentPanel - place additional content here--> 44 <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> 45 <ScrollViewer> 46 <Grid> 47 <Grid.RowDefinitions> 48 <RowDefinition Height="*"/> 49 <RowDefinition Height="Auto"/> 50 </Grid.RowDefinitions> 51 52 <ListBox Grid.Row="0" x:Name="LstBox" Margin="15,0" SelectionMode="Multiple" ItemsSource="{Binding LstModel}" ScrollViewer.VerticalScrollBarVisibility="Disabled"> 53 <ListBox.ItemTemplate> 54 <DataTemplate> 55 <StackPanel Orientation="Horizontal" Margin="0,0,0,20"> 56 <Rectangle Height="100" Width="100" Fill="#FFE5001b" Margin="0,0,9,0"/> 57 <StackPanel> 58 <TextBlock Text="{Binding Name}" TextWrapping="Wrap" Style="{StaticResource PhoneTextLargeStyle}"/> 59 <TextBlock Text="{Binding Discription}" TextWrapping="Wrap" Margin="12,-6,12,0" Style="{StaticResource PhoneTextSubtleStyle}"/> 60 </StackPanel> 61 </StackPanel> 62 </DataTemplate> 63 </ListBox.ItemTemplate> 64 </ListBox> 65 66 <Button Grid.Row="1" x:Name="Buton" Height="72" Content="加载更多" Click="Buton_Click" Visibility="{Binding More, Converter={StaticResource NumToButonVis1}}"/> 67 </Grid> 68 </ScrollViewer> 69 </Grid> 70 </Grid> 71 72 </phone:PhoneApplicationPage>
e、UI xaml.cs

1 using System; 2 using System.Windows; 3 using System.ComponentModel; 4 using Microsoft.Phone.Controls; 5 using System.Collections.ObjectModel; 6 7 namespace LoadingDataDemo 8 { 9 public partial class MainPage : PhoneApplicationPage, INotifyPropertyChanged 10 { 11 // Constructor 12 public MainPage() 13 { 14 InitializeComponent(); 15 App.ViewModel.More.PageLstModelCount = 0; 16 SelfModel = new ObservableCollection<SimpleModel>(); 17 18 this.Loaded += new RoutedEventHandler(MainPage_Loaded); 19 } 20 21 void MainPage_Loaded(object sender, RoutedEventArgs e) 22 { 23 DataContext = App.ViewModel; 24 LstBox.ItemsSource = Model; 25 } 26 27 protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e) 28 { 29 if (!App.ViewModel.IsDataLoaded) 30 { 31 App.ViewModel.LoadData(); 32 } 33 LoadData15(); 34 base.OnNavigatedTo(e); 35 } 36 37 private void ApplicationBarIconButton_Click(object sender, EventArgs e) 38 { 39 foreach (var item in LstBox.SelectedItems) 40 { 41 if(item is SimpleModel) 42 { 43 Model.Remove((SimpleModel)item); 44 App.ViewModel.LstModel.Remove((SimpleModel)item); 45 } 46 } 47 App.ViewModel.More.PageLstModelCount = 0; 48 Model.Clear(); 49 LoadData15(); 50 } 51 52 private void ApplicationBarIconButton_Click_1(object sender, EventArgs e) 53 { 54 LstBox.SelectAll(); 55 } 56 57 private void Buton_Click(object sender, RoutedEventArgs e) 58 { 59 LoadData15(); 60 } 61 62 private ObservableCollection<SimpleModel> SelfModel = null; 63 public ObservableCollection<SimpleModel> Model 64 { 65 get { return SelfModel; } 66 set 67 { 68 SelfModel = value; 69 NotifyPropertyChanged("Model"); 70 } 71 } 72 73 private void LoadData15() 74 { 75 for (int i = 0; i < 8; i++) 76 { 77 if (App.ViewModel.More.PageLstModelCount < App.ViewModel.LstModel.Count) 78 { 79 Model.Add(App.ViewModel.LstModel[App.ViewModel.More.PageLstModelCount]); 80 App.ViewModel.More.PageLstModelCount++; 81 } 82 else 83 { 84 return; 85 } 86 } 87 } 88 89 90 public event PropertyChangedEventHandler PropertyChanged; 91 protected void NotifyPropertyChanged(string propertyName) 92 { 93 if (PropertyChanged != null) 94 { 95 PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 96 } 97 } 98 } 99 }
(5)完成工程代码:猛击