0

我想保存已在多选列表中选中的项目,以便在从页面导航然后返回到选中的项目时可以显示在列表中。目前,当我在检查项目后导航离开然后返回多选列表项目页面时,未保存检查状态。到目前为止,我所拥有的如下

多选列表.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>

多选列表.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;
    }        

那么我将如何保存多选列表中项目的选中状态,以便如果用户导航离开然后返回页面,则显示这些选中的项目?

4

1 回答 1

3

您可以使用多选列表的SelectedItems属性来选择项目。如果您使用SelectionChanged列表上的事件,您可以更新视图模型中的列表以在离开页面时保存。使用blend sdk及其交互 dll,您也可以将事件绑定到视图模型中的命令。

<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>

然后,在您的视图模型中,您可以像这样创建适当的命令和方法。

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 文件和使用语句的视图模型中。

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;
}
于 2013-01-12T17:49:26.537 回答