Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/260.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Windows Phone 8绑定多选列表视图_C#_Xaml_Listview_Windows Phone 8 - Fatal编程技术网

C# Windows Phone 8绑定多选列表视图

C# Windows Phone 8绑定多选列表视图,c#,xaml,listview,windows-phone-8,C#,Xaml,Listview,Windows Phone 8,我在使用列表视图设置绑定多个选择时遇到问题,当我将选择模式切换到“单个”和“多个”之间时,我无法记住这些选择 上下文 我正在创建一个足球教练应用程序。列表视图将显示球员名册。在比赛日,我想用一种简单的方法来选择参加比赛的球员。我想使用多重选择模式,允许用户选择出现的球员。我将在应用程序栏中提供一个按钮,通过转换器控制SelectionMode。它将列表视图从单个切换到多个。这部分很好用。我可以看到列表视图在单视图和多视图之间切换 无法正常工作的部分是所选项目的绑定。我肯定遗漏了什么,因为要可靠地

我在使用列表视图设置绑定多个选择时遇到问题,当我将选择模式切换到“单个”和“多个”之间时,我无法记住这些选择

上下文

我正在创建一个足球教练应用程序。列表视图将显示球员名册。在比赛日,我想用一种简单的方法来选择参加比赛的球员。我想使用多重选择模式,允许用户选择出现的球员。我将在应用程序栏中提供一个按钮,通过转换器控制SelectionMode。它将列表视图从单个切换到多个。这部分很好用。我可以看到列表视图在单视图和多视图之间切换

无法正常工作的部分是所选项目的绑定。我肯定遗漏了什么,因为要可靠地绑定到SelectedItems属性似乎非常困难。到目前为止,最有效的是WinRTXamlToolkit中的ListViewExtensions,这是我在下面的xaml中展示的。在进行选择时,似乎会在视图模式中将项目绑定到backing属性,但是,当SelectionMode切换回Single时,back属性将被清除。而且,没有修改扩展代码,它破坏了我的SelectionMode代码。在_listView上的扩展中出现castastrophic故障。SelectedItems.Clear()。如果删除该行,则SelectionMode将恢复工作

我不想使用WinRTXamlToolkit中的ListViewExtensions。我把它放在这里只是为了让你知道我已经试过了。最后,我正在寻找绑定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=“使用:WinRTXamlToolkit.Controls.Extensions”

视图模型具有以下属性: 名册:可观察收集 iEdit玩家名册:Bool 所选玩家:可观察收集

感谢所有演示绑定多个选择的示例,特别是当它也处理切换选择模式时

谢谢,
汤姆

我也面临着这个问题。当我试图改变转换器中的选择模式时,它并没有按预期工作。我发现的任何解决方法都是使用多选模式,但在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;
        }
    }
}
//
///增强的列表视图
/// 
///选择模式切换:
///该类增强了ListView,支持将选择模式从无/单个更改为多个,然后返回并拥有它
///在更改选择模式时,绑定选定项而不会忘记它们。切换时,基本列表视图将删除所选项目
///从Multiple SelectionMode切换到另一个SelectionMode。
///1)创建SelectedItems 2以绑定到视图模型,因为SelectedItems将删除项目,并且SelectedItems不容易绑定到SelectedItems。
///2)选择更改时,请记住SelectedItems2中的所选项目是用户如何选择或取消选择的。
///3)在SelectionMode设置为Multiple时,使用SelectedItems2中的值填充基础SelectedItems,以便在ListView上选中复选框。
///4)使用_isMergingItems标志忽略通过合并SelectedItem2和SelectedItems2集合而触发的选择更改事件。
/// 
///尚不支持在Multiple SelectionMode下更改SelectedItems2绑定集合。
///为此,我们需要将CollectionChanged事件挂接到绑定的SelectedItems2列表对象上。
///并可能通过合并SelectedItems和SelectedItems2来处理线程问题。
/// 
公共类MyListView:ListView
{
私人住宅项目;
公共MyListView()
{
SelectionChanged+=MyListView\u SelectionChanged;
}
私有void MyListView_SelectionChanged(对象发送者,SelectionChangedEventArgs e)
{
//选择模式不是多个时忽略选择更改事件。
//这主要是因为当从多个更改为单个时,会触发此事件并导致
//要从SelectedItems2中删除的项目不是所需的。
如果(SelectionMode!=ListViewSelectionMode.Multiple){return;}
if(_isMergingItems){return;}
尝试
{
_isMergingItems=true;
var selectedItems2List=SelectedItems2作为IList;
如果(selectedItems2List==null){return;}
foreach(在e.AddedItems中添加var itemToAdd)
{
选择编辑项2列表。添加(要添加的项);
}
foreach(var itemToRemove in e.RemovedItems)
{
选择Editems2列表。删除(itemToRemove);
}
}
最后
{
_isMergingItems=false;
}
}
#区域-依赖属性---
私有静态只读DependencyProperty SelectionMode2Property=DependencyProperty.Register(“SelectionMode2”、typeof(ListViewSelectionMode)、typeof(MyListView)、new PropertyMetadata(ListViewSelectionMode.None、SelectionMode2已更改));
公共列表视图选择模式选择模式2
{
获取{return(ListViewSelectionMode)GetValue(SelectionMode2Property);}
设置{SetValue(SelectionMode2Property,value);}
}
私有静态无效选择
<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>
    private ObservableCollection<Player> _selectedPlayers;

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

            return _selectedPlayers;
        }
    }