我想在多选列表中保存已检查的项目,以便在页面导航时然后返回到已检查的项目可能会显示在列表中。目前,当我在检查项目后离开然后返回到Multiselectlist项目页面时,不会保存选中的状态。到目前为止,我所拥有的内容如下
Multiselectlist.xaml
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<ScrollViewer>
<!--<toolkit:MultiselectList x:Name="ColorList" ItemsSource="{Binding}" Height="88" HorizontalAlignment="Left" VerticalAlignment="Top" >-->
<toolkit:MultiselectList x:Name="ColorList" HorizontalAlignment="Left" VerticalAlignment="Top" Tap="ColorList_Tap">
<toolkit:MultiselectList.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Margin="12,0,0,0" Grid.ColumnSpan="2">
<!--<Rectangle Fill="{Binding Brush}" Width="50" Height="50"/>-->
<CheckBox Background="{Binding Brush}"/>
<TextBlock Text="{Binding Name}" Margin="12,10,0,0"/>
</StackPanel>
</DataTemplate>
</toolkit:MultiselectList.ItemTemplate>
</toolkit:MultiselectList>
</ScrollViewer>
Multiselectlist.xaml.cs
public ColorListPage()
{
InitializeComponent();
solidColorBrushList = new List<ColorItem>()
{
//Color Color = (Color)ColorConverter.ConvertFromString("#FFF0F8FF");
new ColorItem { Brush = ColorHelper.ToSolidColorBrush("#FFF0F8FF"), Name = "alice blue" },
new ColorItem { Brush = ColorHelper.ToSolidColorBrush("#FFFAEBD7"), Name = "antique white" },
new ColorItem { Brush = ColorHelper.ToSolidColorBrush("#FF00FFFF"), Name = "aqua" },
new ColorItem { Brush = ColorHelper.ToSolidColorBrush("#FF7FFFD4"), Name = "aquamarine" },
new ColorItem { Brush = ColorHelper.ToSolidColorBrush("#FFF0FFFF"), Name = "azure" }, //dont translate!?
};
this.ColorList.ItemsSource = solidColorBrushList;
this.Loaded += new RoutedEventHandler(ColorListPage_Loaded);
}
void ColorListPage_Loaded(object sender, RoutedEventArgs e)
{
//show checkboxes when page is loaded
this.ColorList.IsSelectionEnabled = true;
}
private void ColorList_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
DependencyObject tappedElement = e.OriginalSource as UIElement;
MultiselectItem tappedItem = this.FindParentOfType<MultiselectItem>(tappedElement);
ColorItem selectedItem = null;
if (tappedItem != null)
{
// DataContext contains reference to data item
selectedItem = tappedItem.DataContext as ColorItem;
}
if (selectedItem != null)
{
MessageBox.Show(selectedItem.Name + " Tapped");
}
}
private T FindParentOfType<T>(DependencyObject element) where T : DependencyObject
{
T result = null;
DependencyObject currentElement = element;
while (currentElement != null)
{
result = currentElement as T;
if (result != null)
{
break;
}
currentElement = VisualTreeHelper.GetParent(currentElement);
}
return result;
}
那么如何保存Multiselectlist中项目的已检查状态,以便在用户导航然后返回页面时,会显示那些选中的项目?
答案 0 :(得分:3)
您可以使用multiselectlist的SelectedItems
属性来选择项目。如果您在列表中使用SelectionChanged
事件,则可以更新视图模型中的列表,以便在离开页面时进行保存。使用blend sdk及其Interactivity dll,您也可以将事件绑定到viewmodel中的命令。
<phone:PhoneApplicationPage
<!-- the usual xmlns attributes -->
xmlns:vm="clr-namespace:MyApplication.Presentation.ViewModels"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity">
<phone:PhoneApplicationPage.DataContext>
<vm:MyPageViewModel />
</phone:PhoneApplicationPage.DataContext>
<toolkit:MultiselectList x:Name="selectionlist" ItemsSource="{Binding Items}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<i:InvokeCommandAction
Command="{Binding UpdateSelectedCommand}"
CommandParameter="{Binding ElementName=selectionlist, Path=SelectedItems}"/>
</i:EventTrigger>
<i:EventTrigger EventName="Loaded">
<i:InvokeCommandAction
Command="{Binding LoadCommand}"
CommandParameter="{Binding ElementName='selectionlist'}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<toolkit:MultiselectList.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
</toolkit:MultiselectList.ItemTemplate>
</toolkit:MultiselectList>
</phone:PhoneApplicationPage>
然后,在您的viewmodel中,您可以创建相应的命令和方法。
namespace MyApplication.Presentation.ViewModels {
public sealed class MyPageViewModel : DependencyObject {
private readonly ObservableCollection<ItemViewModel> items;
private readonly RoutedCommand load;
private readonly RoutedCommand saveCommand;
private readonly RoutedCommand updateSelectedCommand;
public MyPageViewModel() {
items = new ObservableCollection<ItemViewModel>();
load = new RoutedCommand<MultiselectList>(
m => {
IEnumerable<Item> store = loadItems();
IEnumerable<Item> selected = loadSelectedItems();
populateSelectionList(m, store, selected);
});
updateSelectedCommand = new RoutedCommand<IList>(setSelected);
// use the savecommand on a button or a BindableApplicationBarButton
// or execute the command when you're navigating away from the page
saveCommand = new RoutedCommand<object>(o => storeItems(items));
}
public ICommand LoadCommand {
get { return load; }
}
public ICommand UpdateSelectedCommand {
get { return updateSelectedCommand; }
}
public ICommand SaveCommand {
get { return saveCommand; }
}
private void populateSelectionList(MultiselectList list, IEnumerable<Item> storage, IEnumerable<Item> selected) {
foreach (Item item in selected) {
ItemViewModel viewModel = new ItemViewModel(item);
list.SelectedItems.Add(viewModel);
items.Add(viewModel);
}
foreach (string item in storage) {
bool found = false;
foreach (Item select in selected) {
if (select == item) {
found = true;
break;
}
}
if (!found) {
ItemViewModel viewModel = new ItemViewModel(item);
items.Add(viewModel);
}
}
}
private void setSelected(IList list) {
// triggered when user selects or deselects an item in GUI
foreach (ItemViewModel viewModel in items) {
viewModel.IsSelected = false;
}
foreach (object item in list) {
ItemViewModel item = (ItemViewModel)item;
foreach (ItemViewModel tvm in items) {
if (tvm == item) {
tvm.IsSelected = true;
break;
}
}
}
}
private static void storeItems(IEnumerable<ItemViewModel> enumerable) {
// get all selected items
List<ItemViewModel> selected = new List<ItemViewModel>();
foreach (ItemViewModel viewModel in enumerable) {
if (viewModel.IsSelected) {
selected.Add(viewModel);
}
}
// save selected items in storage
saveSelectedItems(selected);
// save enumerable (i.e. all items) in storage
saveItems(enumerable);
}
private static void saveItems(IEnumerable<ItemViewModel> items) {
// todo: save enumerable to storage
foreach (ItemViewModel item in items) {
//saveItem(item.Model);
}
}
private static IEnumerable<Item> loadItems() {
// todo: load from storage
}
private static void saveSelectedItems(IEnumerable<Item> items) {
// todo: save selected to storage
}
private static IEnumerable<Item> loadSelectedItems() {
// todo: load from storage
}
}
}
注意待办事项。您需要存储和加载某些存储中的项目,例如文件。如果您想将它存储在一个文件中,请查看IsolatedStorage。
如果你在google上搜索,你会找到RoutedCommand类,为了简单起见,它会在下面插入。
Item和ItemViewModel类非常基础,它们只显示显示项目所需的字段。
public class ItemViewModel : INotifyPropertyChanged {
private Item model;
public ItemViewModel(Item item) {
model = item;
item.PropertyChanged += (o,e) => onPropertyChanged(e.Property);
}
public bool IsSelected { get; set; }
public string Name {
get { return model.Name; }
set { model.Name = value; }
}
public event PropertyChangedEventHandler PropertyChanged;
private void onPropertyChanged(string property) {
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) {
handler(this, new PropertyChangedEventArgs(property));
}
}
}
public sealed class Item : INotifyPropertyChanged {
private string name;
public string Name {
get { return name; }
set {
if (name != value) {
name = value;
onPropertyChanged("Name");
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void onPropertyChanged(string property) {
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) {
handler(this, new PropertyChangedEventArgs(property));
}
}
}
如果您愿意,可以将RoutedCommand类放在单独的命名空间中,并将其包含在xaml文件和viewmodels中使用语句。
public class RoutedCommand<TArg> : ICommand {
private readonly Action<TArg> execute;
private readonly Func<TArg, bool> canexecute;
public RoutedCommand(Action<TArg> execute) : this(execute, o => true) { }
public RoutedCommand(Action<TArg> execute, Func<TArg, bool> canexecute) {
this.execute = execute;
this.canexecute = canexecute;
}
public bool CanExecute(object parameter) {
return canexecute((TArg)parameter);
}
public void Execute(object parameter) {
if (CanExecute(parameter)) {
execute((TArg)parameter);
}
}
public event EventHandler CanExecuteChanged;
}