编写Asp.net的同学,经常会遇到一个Repeater 或者一个GridView ,当用户点击编辑状态时我们的列表组件会自动跳转到可选择(可供删除、编辑、选择等)状态。这时候一般的做法都会在组件的前方自动生成一系列复选框“CheckBox”,需要删除/选择哪行时只要在前方的复选框勾一下,便可以得到该行的数据或者行ID等。
上面的做法是一个比较典型的Web做法,那么在WP7 里面要实现这样的效果如何实现呢?有些同学就会说了,那简单使用ListBox 在它的数据模板里面添加一个CheckBox不就完事了吗?是的,这样是一种做法,但带来的问题是你得去控制他选中哪行并且得到哪行的ID,并且在WP7 有限的屏幕中这种做法比较不妥,当用户想做选择时,我们才让对应的行有可供选择的状态才更佳。而这种做法在传统的WP7控件中,是没有的。因为我们必须时时去控制它的复选框显示或者隐藏,但在这里我推荐大家一个组件,自带CheckBOx并且默认有两种状态,一种为普通状态即呈现数据显示给用户,如下图:
另外一种状态为可选择状态,即用户可以对相应的行做删除等操作,如下图:
该组件的下载地址为:WindowsPhoneListBoxWithCheckBoxesControl
下面给出该组件的详细用法:
做过.Net 开发的对于如何使该组件的应该很清楚,这里将跳过此步骤。
如上图,该组件编写的XAML代码为如下:
< my:ListBoxWithCheckBoxes Name ="listBoxWithBoxes" Margin ="0,0,0,0" ItemsSource =" {Binding SimpleModels} " > < ListBox.ItemTemplate > < DataTemplate > < StackPanel Orientation ="Horizontal" Margin ="0,0,0,20" > < Rectangle Height ="100" Width ="100" Fill ="#FFE5001b" Margin ="12,0,9,0" /> < StackPanel > < TextBlock Text =" {Binding Name} " TextWrapping ="Wrap" Style =" {StaticResource PhoneTextLargeStyle} " /> < TextBlock Text =" {Binding Description} " TextWrapping ="Wrap" Margin ="12,-6,12,0" Style =" {StaticResource PhoneTextSubtleStyle} " /> </ StackPanel > </ StackPanel > </ DataTemplate > </ ListBox.ItemTemplate > </ my:ListBoxWithCheckBoxes >
如上代码的数据模板,并未出现有CheckBox 控件,因为该组件己经将CheckBox控件整合在里面的选择状态中了。下面是具体如何为该组件添加数据。
首先该组件对应的行有标题和描述,这个在上面XAML代码中的数据模板可以看得出,查看该组件的ItemSource ,一起来看看它的代码是如何编写的:
public class SimpleModel : INotifyPropertyChanged { protected string itsName; protected string itsDescription; public event PropertyChangedEventHandler PropertyChanged; public string Name { get { return this .itsName; } set { this .itsName = value; NotifyPropertyChanged( " Name " ); } } public string Description { get { return this .itsDescription; } set { this .itsDescription = value; NotifyPropertyChanged( " Description " ); } } protected void NotifyPropertyChanged( string thePropertyName) { if ( this .PropertyChanged != null ) { this .PropertyChanged( this , new PropertyChangedEventArgs(thePropertyName)); } } }
代码比较简单,封装了两个属性分别为他们注册PropertyChanged 事件响应数据变化。
而这个MODEL的数据来源于如下代码:
public class ListModel : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; public ObservableCollection < SimpleModel > SimpleModels { get ; private set ; } public bool IsDataLoaded { get ; private set ; } public ListModel() { this .SimpleModels = new ObservableCollection < SimpleModel > (); } /// <summary> /// 加载数据 /// </summary> public void LoadData() { for ( int i = 1 ; i < 1000 ; i ++ ) { this .SimpleModels.Add( new SimpleModel() { Name = " 第 " + i + " 项 " , Description = " 这是第 " + i + " 项数据 " }); } this .IsDataLoaded = true ; } protected void NotifyPropertyChanged( string thePropertyName) { if ( this .PropertyChanged != null ) { this .PropertyChanged( this , new PropertyChangedEventArgs(thePropertyName)); } } }
代码跟上边的代码差不多,这里多了调用加载数据的方法LoadData()为上面的每个Model赋值。而加载代码首先为其添加一个全局属性:
public static ListBoxWithCheckBox.ViewModel.ListModel viewModel = null ; // 获取数据 public static ViewModel.ListModel ViewModel { get { if (viewModel == null ) { viewModel = new ViewModel.ListModel(); } return viewModel; } }
转到MainPage的code behind 代码里面,在构造函数里面为DataContext 赋值,这里赋值的话上下文即可得到数据源,代码如下:
DataContext = App.ViewModel;
当应用程序导航进来时,调用加载全局属性去执行抓取数据的方法,代码如下:
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e) { if ( ! App.ViewModel.IsDataLoaded) { App.ViewModel.LoadData(); } base .OnNavigatedTo(e); }
最后的运行效果,我们选择第1 、2条数据做为欲删除的对象,然后删除看有啥变化?
点击删除后的效果:
mainPage 的code behind 完整代码如下:
完整代码 using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; using Microsoft.Phone.Controls; using Microsoft.Phone.Shell; using ListBoxWithCheckBox.ViewModel; namespace ListBoxWithCheckBox{ public partial class MainPage : PhoneApplicationPage { private ApplicationBar applicationBarChoose; private ApplicationBarIconButton applicationBarIconButtonChoose; private ApplicationBar applicationBarDeleteOrCancel; private ApplicationBarIconButton applicationBarIconButtonDelete; private ApplicationBarIconButton applicationBarIconButtonCancel; // Constructor public MainPage() { InitializeComponent(); ConstructApplicationBar(); DataContext = App.ViewModel; this .Loaded += new RoutedEventHandler(MainPage_Loaded); } void MainPage_Loaded( object sender, RoutedEventArgs e) { } protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e) { if ( ! App.ViewModel.IsDataLoaded) { App.ViewModel.LoadData(); } base .OnNavigatedTo(e); } /// <summary> /// 构建应用程序条 /// </summary> private void ConstructApplicationBar() { #region --应用程序条“选择”菜单-- this .applicationBarChoose = new ApplicationBar(); this .applicationBarIconButtonChoose = new ApplicationBarIconButton( new Uri( " /content/ApplicationBar.Choose.png " ,UriKind.Relative)); this .applicationBarIconButtonChoose.Text = " 选择 " ; this .applicationBarIconButtonChoose.Click += new EventHandler(applicationBarIconButtonChoose_Click); this .applicationBarChoose.Buttons.Add( this .applicationBarIconButtonChoose); this .applicationBarChoose.IsMenuEnabled = true ; this .applicationBarChoose.IsVisible = true ; this .ApplicationBar = this .applicationBarChoose; #endregion this .applicationBarDeleteOrCancel = new ApplicationBar(); #region --删除-- this .applicationBarIconButtonDelete = new ApplicationBarIconButton( new Uri( " /content/ApplicationBar.Delete.png " ,UriKind.Relative)); this .applicationBarIconButtonDelete.Text = " 删除 " ; this .applicationBarIconButtonDelete.Click += new EventHandler(applicationBarIconButtonDelete_Click); #endregion #region --取消-- this .applicationBarIconButtonCancel = new ApplicationBarIconButton( new Uri( " /content/ApplicationBar.Cancel.png " ,UriKind.Relative)); this .applicationBarIconButtonCancel.Text = " 取消 " ; this .applicationBarIconButtonCancel.Click += new EventHandler(applicationBarIconButtonCancel_Click); #endregion this .applicationBarDeleteOrCancel.Buttons.Add( this .applicationBarIconButtonDelete); this .applicationBarDeleteOrCancel.Buttons.Add( this .applicationBarIconButtonCancel); this .applicationBarDeleteOrCancel.IsMenuEnabled = true ; this .applicationBarDeleteOrCancel.IsVisible = true ; } /// <summary> /// listBox 为可选择状态 /// </summary> private void SwitchToChooseState() { this .listBoxWithBoxes.IsInChooseState = true ; this .ApplicationBar = this .applicationBarDeleteOrCancel; } /// <summary> /// listBox 为普通状态 /// </summary> private void SwitchToNormalState() { this .listBoxWithBoxes.IsInChooseState = false ; this .ApplicationBar = this .applicationBarChoose; } /// <summary> /// 取消操作 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> void applicationBarIconButtonCancel_Click( object sender, EventArgs e) { SwitchToNormalState(); } /// <summary> /// 删除操作 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> void applicationBarIconButtonDelete_Click( object sender, EventArgs e) { if (MessageBox.Show( " 你确定要删除选中项吗? " , " 提示 " ,MessageBoxButton.OKCancel) == MessageBoxResult.OK) { foreach (SimpleModel item in this .listBoxWithBoxes.SelectedItems) { App.ViewModel.SimpleModels.Remove(item); } SwitchToNormalState(); } } /// <summary> /// 选择操作 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> void applicationBarIconButtonChoose_Click( object sender, EventArgs e) { SwitchToChooseState(); } }}
这里推荐一个小技巧,当我们编写动态数据时,又不想运行即想从代码IDE看到运行效果,类似于这样:
这个效果还是要借用PhoneApplicationPage 的DataContext属性,具体如下编写代码:
编写一个数据xaml命名为:ViewModelSampleData.xaml 文件,该文件负责为SimpleModels 做数据,代码如下: < viewModels:ListModel xmlns ="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x ="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:viewModels ="clr-namespace:ListBoxWithCheckBox.ViewModel" > < viewModels:ListModel.SimpleModels > < viewModels:SimpleModel Name ="测试第一项" Description ="这是测试的第一个节点" /> < viewModels:SimpleModel Name ="测试第二项" Description ="这是测试的第二个节点" /> </ viewModels:ListModel.SimpleModels > </ viewModels:ListModel >在MainPage文件的XAML界面为DataContext赋值,代码如下: d:DataContext="{d:DesignData ViewModelSampleData.xaml}"
Tip:该效果只运用于没有运行即可查看效果,运行后将会忽略。
怎么样,该组件不错吧,大家下载后试试吧。
源码下载:
ListBoxWithCheckBox Demo
转载于:https://www.cnblogs.com/TerryBlog/archive/2011/02/20/1959206.html
相关资源:数据结构—成绩单生成器