C# Windows Phone 8绑定多选列表视图
我在使用列表视图设置绑定多个选择时遇到问题,当我将选择模式切换到“单个”和“多个”之间时,我无法记住这些选择 上下文 我正在创建一个足球教练应用程序。列表视图将显示球员名册。在比赛日,我想用一种简单的方法来选择参加比赛的球员。我想使用多重选择模式,允许用户选择出现的球员。我将在应用程序栏中提供一个按钮,通过转换器控制SelectionMode。它将列表视图从单个切换到多个。这部分很好用。我可以看到列表视图在单视图和多视图之间切换 无法正常工作的部分是所选项目的绑定。我肯定遗漏了什么,因为要可靠地绑定到SelectedItems属性似乎非常困难。到目前为止,最有效的是WinRTXamlToolkit中的ListViewExtensions,这是我在下面的xaml中展示的。在进行选择时,似乎会在视图模式中将项目绑定到backing属性,但是,当SelectionMode切换回Single时,back属性将被清除。而且,没有修改扩展代码,它破坏了我的SelectionMode代码。在_listView上的扩展中出现castastrophic故障。SelectedItems.Clear()。如果删除该行,则SelectionMode将恢复工作 我不想使用WinRTXamlToolkit中的ListViewExtensions。我把它放在这里只是为了让你知道我已经试过了。最后,我正在寻找绑定SelectedItems的正确解决方案 下面是列表视图XAMLC# Windows Phone 8绑定多选列表视图,c#,xaml,listview,windows-phone-8,C#,Xaml,Listview,Windows Phone 8,我在使用列表视图设置绑定多个选择时遇到问题,当我将选择模式切换到“单个”和“多个”之间时,我无法记住这些选择 上下文 我正在创建一个足球教练应用程序。列表视图将显示球员名册。在比赛日,我想用一种简单的方法来选择参加比赛的球员。我想使用多重选择模式,允许用户选择出现的球员。我将在应用程序栏中提供一个按钮,通过转换器控制SelectionMode。它将列表视图从单个切换到多个。这部分很好用。我可以看到列表视图在单视图和多视图之间切换 无法正常工作的部分是所选项目的绑定。我肯定遗漏了什么,因为要可靠地
<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;
}
}