編寫Asp.net的同學,經常會遇到一個Repeater 或者一個GridView ,當使用者點選編輯狀态時我們的清單元件會自動跳轉到可選擇(可供删除、編輯、選擇等)狀态。這時候一般的做法都會在元件的前方自動生成一系列複選框“CheckBox”,需要删除/選擇哪行時隻要在前方的複選框勾一下,便可以得到該行的資料或者行ID等。
上面的做法是一個比較典型的Web做法,那麼在WP7 裡面要實作這樣的效果如何實作呢?有些同學就會說了,那簡單使用ListBox 在它的資料模闆裡面添加一個CheckBox不就完事了嗎?是的,這樣是一種做法,但帶來的問題是你得去控制他選中哪行并且得到哪行的ID,并且在WP7 有限的螢幕中這種做法比較不妥,當使用者想做選擇時,我們才讓對應的行有可供選擇的狀态才更佳。而這種做法在傳統的WP7控件中,是沒有的。因為我們必須時時去控制它的複選框顯示或者隐藏,但在這裡我推薦大家一個元件,自帶CheckBOx并且預設有兩種狀态,一種為普通狀态即呈現資料顯示給使用者,如下圖:
另外一種狀态為可選擇狀态,即使用者可以對相應的行做删除等操作,如下圖:
下面給出該元件的詳細用法:
做過.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 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)
代碼跟上邊的代碼差不多,這裡多了調用加載資料的方法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)
/// 建構應用程式條
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);
#region --取消--
this.applicationBarIconButtonCancel = new ApplicationBarIconButton(new Uri("/content/ApplicationBar.Cancel.png",UriKind.Relative));
this.applicationBarIconButtonCancel.Text = "取消";
this.applicationBarIconButtonCancel.Click += new EventHandler(applicationBarIconButtonCancel_Click);
this.applicationBarDeleteOrCancel.Buttons.Add(this.applicationBarIconButtonDelete);
this.applicationBarDeleteOrCancel.Buttons.Add(this.applicationBarIconButtonCancel);
this.applicationBarDeleteOrCancel.IsMenuEnabled = true;
this.applicationBarDeleteOrCancel.IsVisible = true;
/// listBox 為可選擇狀态
private void SwitchToChooseState()
this.listBoxWithBoxes.IsInChooseState = true;
this.ApplicationBar = this.applicationBarDeleteOrCancel;
/// listBox 為普通狀态
private void SwitchToNormalState()
this.listBoxWithBoxes.IsInChooseState = false;
/// 取消操作
/// <param name="sender"></param>
/// <param name="e"></param>
void applicationBarIconButtonCancel_Click(object sender, EventArgs e)
SwitchToNormalState();
/// 删除操作
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();
/// 選擇操作
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:該效果隻運用于沒有運作即可檢視效果,運作後将會忽略。
怎麼樣,該元件不錯吧,大家下載下傳後試試吧。
源碼下載下傳:
<a href="http://files.cnblogs.com/TerryBlog/ListBoxWithCheckBox.rar" target="_blank">ListBoxWithCheckBox Demo</a>
本文轉自 terry_龍 51CTO部落格,原文連結:http://blog.51cto.com/terryblog/497004,如需轉載請自行聯系原作者