【WP7进阶】——分享一个可供切换状态的ListBox组件

编写Asp.net的同学,经常会遇到一个Repeater 或者一个GridView ,当用户点击编辑状态时我们的列表组件会自动跳转到可选择(可供删除、编辑、选择等)状态。这时候一般的做法都会在组件的前方自动生成一系列复选框“CheckBox”,需要删除/选择哪行时只要在前方的复选框勾一下,便可以得到该行的数据或者行ID等。

  上面的做法是一个比较典型的Web做法,那么在WP7 里面要实现这样的效果如何实现呢?有些同学就会说了,那简单使用ListBox 在它的数据模板里面添加一个CheckBox不就完事了吗?是的,这样是一种做法,但带来的问题是你得去控制他选中哪行并且得到哪行的ID,并且在WP7 有限的屏幕中这种做法比较不妥,当用户想做选择时,我们才让对应的行有可供选择的状态才更佳。而这种做法在传统的WP7控件中,是没有的。因为我们必须时时去控制它的复选框显示或者隐藏,但在这里我推荐大家一个组件,自带CheckBOx并且默认有两种状态,一种为普通状态即呈现数据显示给用户,如下图:

另外一种状态为可选择状态,即用户可以对相应的行做删除等操作,如下图:

该组件的下载地址为:WindowsPhoneListBoxWithCheckBoxesControl

下面给出该组件的详细用法:

做过.Net 开发的对于如何使该组件的应该很清楚,这里将跳过此步骤。

  如上图,该组件编写的XAML代码为如下:

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --> < my:ListBoxWithCheckBoxes Name ="listBoxWithBoxes" Margin ="0,0,0,0" ItemsSource =" {BindingSimpleModels} " >
< 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 =" {BindingName} " TextWrapping ="Wrap" Style =" {StaticResourcePhoneTextLargeStyle} " />
< TextBlock Text =" {BindingDescription} " TextWrapping ="Wrap" Margin ="12,-6,12,0" Style =" {StaticResourcePhoneTextSubtleStyle} " />
</ StackPanel >
</ StackPanel >
</ DataTemplate >
</ ListBox.ItemTemplate >
</ my:ListBoxWithCheckBoxes >

如上代码的数据模板,并未出现有CheckBox 控件,因为该组件己经将CheckBox控件整合在里面的选择状态中了。下面是具体如何为该组件添加数据。

首先该组件对应的行有标题和描述,这个在上面XAML代码中的数据模板可以看得出,查看该组件的ItemSource ,一起来看看它的代码是如何编写的:

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --> public class SimpleModel:INotifyPropertyChanged
{
protected string itsName;
protected string itsDescription;

public event PropertyChangedEventHandlerPropertyChanged;

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的数据来源于如下代码:

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --> public class ListModel:INotifyPropertyChanged
{
public event PropertyChangedEventHandlerPropertyChanged;

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赋值。而加载代码首先为其添加一个全局属性:

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --> public static ListBoxWithCheckBox.ViewModel.ListModelviewModel = null ;

// 获取数据
public static ViewModel.ListModelViewModel
{
get {
if (viewModel == null )
{
viewModel
= new ViewModel.ListModel();
}
return viewModel;
}
}

转到MainPage的code behind 代码里面,在构造函数里面为DataContext 赋值,这里赋值的话上下文即可得到数据源,代码如下:

DataContext = App.ViewModel;

当应用程序导航进来时,调用加载全局属性去执行抓取数据的方法,代码如下:

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --> protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgse)
{
if ( ! App.ViewModel.IsDataLoaded)
{
App.ViewModel.LoadData();
}
base .OnNavigatedTo(e);
}

最后的运行效果,我们选择第1 、2条数据做为欲删除的对象,然后删除看有啥变化?

点击删除后的效果:

mainPage 的code behind 完整代码如下:

完整代码
<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --> 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 ApplicationBarapplicationBarChoose;
private ApplicationBarIconButtonapplicationBarIconButtonChoose;

private ApplicationBarapplicationBarDeleteOrCancel;
private ApplicationBarIconButtonapplicationBarIconButtonDelete;
private ApplicationBarIconButtonapplicationBarIconButtonCancel;

// Constructor
public MainPage()
{
InitializeComponent();
ConstructApplicationBar();
DataContext
= App.ViewModel;
this .Loaded += new RoutedEventHandler(MainPage_Loaded);
}

void MainPage_Loaded( object sender,RoutedEventArgse)
{

}

protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgse)
{
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>
/// <paramname="sender"></param>
/// <paramname="e"></param>
void applicationBarIconButtonCancel_Click( object sender,EventArgse)
{
SwitchToNormalState();
}

/// <summary>
/// 删除操作
/// </summary>
/// <paramname="sender"></param>
/// <paramname="e"></param>
void applicationBarIconButtonDelete_Click( object sender,EventArgse)
{
if (MessageBox.Show( " 你确定要删除选中项吗? " , " 提示 " ,MessageBoxButton.OKCancel) == MessageBoxResult.OK)
{
foreach (SimpleModelitem in this .listBoxWithBoxes.SelectedItems)
{
App.ViewModel.SimpleModels.Remove(item);
}
SwitchToNormalState();
}
}

/// <summary>
/// 选择操作
/// </summary>
/// <paramname="sender"></param>
/// <paramname="e"></param>
void applicationBarIconButtonChoose_Click( object sender,EventArgse)
{
SwitchToChooseState();
}
}
}

这里推荐一个小技巧,当我们编写动态数据时,又不想运行即想从代码IDE看到运行效果,类似于这样:

这个效果还是要借用PhoneApplicationPage 的DataContext属性,具体如下编写代码:

  • 编写一个数据xaml命名为:ViewModelSampleData.xaml 文件,该文件负责为SimpleModels 做数据,代码如下:
    <!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --> < 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赋值,代码如下:
    <!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --> d:DataContext="{d:DesignDataViewModelSampleData.xaml}"

Tip:该效果只运用于没有运行即可查看效果,运行后将会忽略。

怎么样,该组件不错吧,大家下载后试试吧。

源码下载:

ListBoxWithCheckBox Demo


评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值