繁体   English   中英

Windows Phone 8绑定多个选择ListView

[英]Windows Phone 8 Binding Multiple Selection ListView

我在使用“列表视图”设置绑定多个选择时遇到麻烦,并且在将“选择模式”切换到“单个”和“多个”之间时还记得选择。

上下文

我正在创建一个足球教练应用程序。 列表视图将显示播放器名册。 在比赛当天,我希望有一种简单的方法来选择出现的玩家。 我想使用“多重选择”模式来允许用户选择出现的球员。 我将在应用程序栏中提供一个按钮,该按钮将通过转换器控制SelectionMode。 它将列表视图从单个切换到多个。 这部分工作正常。 我可以看到列表视图在单个和多个之间切换。

不能正常工作的部分是所选项目的绑定。 我必须缺少一些东西,因为要可靠地绑定到SelectedItems属性似乎非常困难。 到目前为止,最有效的方法是WinRTXamlToolkit中的ListViewExtentions,这是我在下面的xaml中显示的内容。 进行选择时,似乎在视图模式下将项目绑定到backing属性,但是,当SelectionMode切换回Single时,将清除back属性。 另外,在不修改扩展代码的情况下,它破坏了我的SelectionMode代码。 _listView.SelectedItems.Clear()上的扩展名中有一个灾难性的失败。 如果我删除该行,则SelectionMode将恢复工作。

我不在乎使用WinRTXamlToolkit中的ListViewExtentions。 我只在这里展示它,所以您知道我已经尝试过了。 最终,我正在寻找绑定SelectedItems的正确解决方案。

这是列表视图XAML。

<ListView ItemsSource="{Binding Roster}"
          toolkitExt:ListViewExtensions.BindableSelection="{Binding SelectedPlayers, Mode=TwoWay}"      
          SelectionMode="{Binding IsEditingGameRoster, Converter={StaticResource ListViewSelectionModeFromBooleanNoneOrMultipleConverter}}">
<ListView.ItemTemplate>
    <DataTemplate>
        <!-- List View Display  Not important for describing problem. -->
    </DataTemplate>
</ListView.ItemTemplate>

命名空间为:xmlns:toolkitExt =“ using:WinRTXamlToolkit.Controls.Extensions”

视图模型具有以下属性:成员名册:ObservableCollection IsEditingGameRoster:Bool SelectedPlayers:ObservableCollection

感谢您展示任何绑定多重选择的示例,尤其是如果它也处理切换SelectionMode的示例。

谢谢汤姆

我也面临这个问题。 当我尝试更改转换器中的选择模式时,它无法按预期工作。 我发现的任何解决方法都是使用多个选择模式,但是在具有添加/删除的项目的CollectionChanged事件中运行。 例如,如果我需要单选模式,我会将选择重写为新的选定项目。

像这样:

private void OnSelectedPlayersChanged(object sender, NotifyCollectionChangedEventArgs e)
{
        if (e.Action == NotifyCollectionChangedAction.Add)
        {
            if (this.SelectionMode == Mode.Once)
            {
                SynchronizationContextProvider.UIThreadSyncContext.Post((d) =>
                {
                    this.SelectedPlayers.Clear();
                    this.SelectedPlayers.Add((Players)e.NewItems[0]);
                }, null);
            }
        }

        if (e.Action == NotifyCollectionChangedAction.Remove)
        {
            //some logic
        }
}

到目前为止,这是最好的选择。 如果您发现更好的东西,我将很乐意使用它。

我最终解决了我希望看到的问题,但仍然不够完美。 我最终创建了ListView的子类,并添加了两个属性SelectedItems2和SelectionMode2。 如果有人可以帮助调整以下代码,以便我可以重用SelectedItems和SelectionMode,则可以使解决方案更加接近完美。

子类代码

/// <summary>
/// Enhanced List View
/// 
/// SeletionMode Switching:
/// This class enhances ListView to support changing the selection mode from None/Single to Multiple and back and having it
/// bind the selected items without forgetting them when changing selection mode.  The base ListView will remove the selected items when switching
/// from Multiple SelectionMode to another SelectionMode.
/// 1) Created SelectedItems2 to bind to View Model as SelectedItems will have items removed and SelectedItems is not easy to bind to SelectedItems.
/// 2) On SelectionChanged, remember the selected items in SelectedItems2 how the user selected or unselected them.
/// 3) On SelectionMode set to Multiple, fill the underlying SelectedItems with the values from SelectedItems2 so that the checkboxes are checked on the ListView.
/// 4) Use _isMergingItems flag to ignore selection changed events being fired by merging of the SelectedItem2 and SelectedItems2 collections.
/// 
/// Doesn't support changing SelectedItems2 bound collection while in Multiple SelectionMode yet.
/// To do so we would need to hook the CollectionChanged event on the SelectedItems2 List object that is bound.
/// and likely handle threading issues with the merging of SelectedItems and SelectedItems2.
/// </summary>
public class MyListView : ListView
{
    private bool _isMergingItems;

    public MyListView()
    {
        SelectionChanged += MyListView_SelectionChanged;
    }

    private void MyListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        // Ignore selection changed event when selection mode is not multiple.
        // This is mainly here because when changing from Multiple to Single, this event is fired and will cause
        // the items to be removed from SelectedItems2 which is not what is desired.
        if (SelectionMode != ListViewSelectionMode.Multiple) { return; }
        if (_isMergingItems) { return; }

        try
        {
            _isMergingItems = true;

            var selectedItems2List = SelectedItems2 as IList;
            if (selectedItems2List == null) { return; }

            foreach (var itemToAdd in e.AddedItems)
            {
                selectedItems2List.Add(itemToAdd);
            }

            foreach (var itemToRemove in e.RemovedItems)
            {
                selectedItems2List.Remove(itemToRemove);
            }
        }
        finally
        {
            _isMergingItems = false;
        }
    }

    #region --- Dependency Properties ---

    private static readonly DependencyProperty SelectionMode2Property = DependencyProperty.Register("SelectionMode2", typeof(ListViewSelectionMode), typeof(MyListView), new PropertyMetadata(ListViewSelectionMode.None, SelectionMode2Changed));

    public ListViewSelectionMode SelectionMode2
    {
        get { return (ListViewSelectionMode)GetValue(SelectionMode2Property); }
        set { SetValue(SelectionMode2Property, value); }
    }

    private static void SelectionMode2Changed(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {

        var listView = d as MyListView;
        var value = (ListViewSelectionMode)e.NewValue;

        // Set the underlying selection mode property to cause the control to 
        // change to and from Multiple selection mode.
        listView.SelectionMode = value;

        // When Multiple selction mode, we will need to load the underlying SelectedItems of the ListView
        // so that the checkboxes are checked appropriatly.  When the selection mode is changed the underlying ListView
        // removes the selected items.
        if (value == ListViewSelectionMode.Multiple)
        {
            listView.FillUnderlyingSelectedItems();
        }
    }

    private static readonly DependencyProperty SelectedItems2Property = DependencyProperty.Register("SelectedItems2", typeof(object), typeof(MyListView), null);

    /// <summary>
    /// SelectedItems2 is used as the property to bind the selected items to the ViewModel.
    /// Using a List as the data type did not seem to work for binding.  Since ItemSource is an object on the base class
    /// object was chosen for this property as well.
    /// 
    /// However, SelectedItems2 will need to bind to IList in order for it to work properly.
    /// </summary>
    public object SelectedItems2
    {
        get { return (object)GetValue(SelectedItems2Property); }
        set { SetValue(SelectedItems2Property, value); }
    }

    #endregion

    private void FillUnderlyingSelectedItems()
    {
        var selectedItems2List = SelectedItems2 as IList;
        if (selectedItems2List == null) { return; }

        try
        {
            _isMergingItems = true;

            foreach (var item in selectedItems2List)
            {
                SelectedItems.Add(item);
            }
        }
        finally
        {
            _isMergingItems = false;
        }
    }
}

用法:XAML

<localUI:MyListView ItemsSource="{Binding Roster}"
          SelectedItems2="{Binding SelectedPlayers}"
          SelectionMode2="{Binding IsEditingGameRoster, Converter={StaticResource ListViewSelectionModeFromBooleanNoneOrMultipleConverter}}">
    <ListView.ItemTemplate>
        <DataTemplate>
            <!-- List View Display  Not important for describing problem. -->
        </DataTemplate>
    </ListView.ItemTemplate>
</localUI:MyListView>

用法:ViewModel

    private ObservableCollection<Player> _selectedPlayers;

    public ObservableCollection<Player> SelectedPlayers
    {
        get
        {
            if (_selectedPlayers == null)
            {
                _selectedPlayers = new ObservableCollection<Player>();
            }

            return _selectedPlayers;
        }
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM