Wpf 列表框,单击时选择并取消选择。。。?
我需要一个列表框,在第一次单击时选择,在第二次单击时取消选择,以便在任何时候只选择零个或一个项目 按住crtl键时,选择/取消选择在列表框中实现(使用SelectionMode=“Single”),但不幸的是,我的用户都不知道这一点 使用SelectionMode=“Multiple”我们拥有我想要的确切功能,只是您可以选择多个项目 更多背景: 我希望用户首先选择要登录的安装,然后提供凭据(以及其他一些选择) 为了实现这一点,我使用了一个扩展内容的列表框。为了帮助展开,我在listboxitem左侧制作了一个三角形,未展开时指向右侧,选中listboxitem时指向下方 因此,首先用户在安装上看到列表,然后,当用户通过选择来选择他想要的项目时,listboxitem将扩展到他需要输入的其余信息。这很好,工作也很好,但测试报告显示,他们希望再次单击三角形以取消选择(从而折叠展开的部分)。我必须承认,我也单击了·%&箭头,期望该操作会导致崩溃…:-( 任何人都知道如何实现这一点(最好没有代码隐藏)?试试: 您可以使用切换按钮作为详细内容的“扩展器”。 切换按钮的“IsChecked”属性可以绑定到项的IsSelected属性 代码如下:Wpf 列表框,单击时选择并取消选择。。。?,wpf,xaml,listbox,selection,listboxitem,Wpf,Xaml,Listbox,Selection,Listboxitem,我需要一个列表框,在第一次单击时选择,在第二次单击时取消选择,以便在任何时候只选择零个或一个项目 按住crtl键时,选择/取消选择在列表框中实现(使用SelectionMode=“Single”),但不幸的是,我的用户都不知道这一点 使用SelectionMode=“Multiple”我们拥有我想要的确切功能,只是您可以选择多个项目 更多背景: 我希望用户首先选择要登录的安装,然后提供凭据(以及其他一些选择) 为了实现这一点,我使用了一个扩展内容的列表框。为了帮助展开,我在listboxitem
<ListBox SelectionMode="Single">
<ListBox.ItemsSource>
<x:Array Type="{x:Type sys:String}">
<sys:String>test1</sys:String>
<sys:String>test2</sys:String>
<sys:String>test3</sys:String>
<sys:String>test4</sys:String>
<sys:String>test5</sys:String>
<sys:String>test6</sys:String>
</x:Array>
</ListBox.ItemsSource>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<ToggleButton IsChecked="{Binding
RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type ListBoxItem}},
Path=IsSelected}"
>btn</ToggleButton>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
测试1
测试2
测试3
测试4
测试5
测试6
btn
工作原理:
在Listbox中只能选择一个项目。当我们选择一个项目时,切换程序会展开,因为他的IsChecked绑定到其父ListBoxItem的ListBoxItem.IsSelected(ListBoxItem是一个围绕每个项目内容的控件)。
由于selectionMode是单一模式,因此一旦选择了另一项,就会发生以下情况:
- 取消选择实际选定的项目
- 通过绑定,触发器也会被取消选中
- 选择新项目
- 新项目切换器通过其绑定进行检查
如果只是实际选择的项目的切换器被取消选中,那么该项目将通过绑定取消自身选择…执行此操作的常用方法是将
SelectionMode
模式设置为Multiple
,然后在SelectionChanged
事件中取消选择除新选择项目之外的所有项目
请参阅以下链接
<ListBox local:ListBoxSelectionBehavior.ClickSelection="True"
...>
我的解决方案是将ListBox SelectionMode设置为Multiple,添加方法禁止SelectionButone on Click事件,然后只允许一个选定项,如下所示:
Private Sub forbidSelectionButOne(sender As Object, e As MouseButtonEventArgs)
Dim lv As ListView = TryCast(sender, ListView)
If lv IsNot Nothing Then
If lv.SelectedIndex <> getCausesListViewItemIndex(sender, e) Then
lv.SelectedIndex = getCausesListViewItemIndex(sender, e)
e.Handled = True
End If
lv.Focus()
End If
End Sub
我允许自己补充Fredrik对UWP和.NET Framework 4.7的回答:
公共静态类ListBoxSelectionBehavior
{
公共静态只读从属属性ClickSelectionProperty=
DependencyProperty.RegisterAttached(“单击选择”,
类型(bool),
类型(ListBoxSelectionBehavior),
新属性元数据(false,OnClickSelectionChanged));
公共静态布尔GetClickSelection(DependencyObject对象对象)
{
返回(bool)对象获取值(点击选择属性);
}
公共静态无效设置单击选择(DependencyObject对象,布尔值)
{
对象设置值(单击SelectionProperty,value);
}
单击SelectionChanged(DependencyObject dpo、DependencyPropertyChangedEventArgs e)时的私有静态无效
{
如果(dpo是ListBox ListBox)
{
if((bool)e.NewValue==true)
{
listBox.SelectionMode=SelectionMode.Multiple;
listBox.SelectionChanged+=OnSelectionChanged;
}
其他的
{
listBox.SelectionChanged-=OnSelectionChanged;
}
}
}
SelectionChanged上的静态无效(对象发送者,SelectionChangedEventArgs e)
{
如果(e.AddedItems.Count>0)
{
ListBox ListBox=发送方作为ListBox;
var valid=e.AddedItems[0];
foreach(新ArrayList(listBox.SelectedItems.ToArray())中的变量项)
{
如果(项目!=有效)
{
列表框。选择编辑项。删除(项);
}
}
}
}
}
比这更简单
只需使用SelectionMode=“Multiple”添加标志combain
我对选择时的扩展没有问题,问题是让列表框一次只选择一个项目,并在第二次单击时取消选择。但它确实做到了这一点。在切换按钮时,它展开并选择项目。在第二次单击时,它折叠并取消选择项目。最多选择1个项目。诀窍是双向绑定正在禁用ListBoxItem的IsSelected属性。只需尝试一下即可。I stand correct,您是对的,解决方案非常出色。谢谢!我必须说,我有点不确定这实际上是如何工作的?1.单击切换按钮->选中tb->选中listviewitem->未选中任何其他listviewitem 2.再次单击tb在->tb未选中->listviewitem未选中…这是否正确?我在答案中编辑了解释。是的,正是这样。你知道为什么我无法通过相同的切换按钮取消选择ListBoxItem。只有选择有效。我更喜欢此解决方案,因为它不涉及UI el的技巧虽然本规范可能回答了问题,但提供了关于本规范为什么和/或如何解释的额外上下文
Private Function getCausesListViewItemIndex(ByVal sender As Object, e As RoutedEventArgs) As Integer
Dim dep As DependencyObject = TryCast(e.OriginalSource, DependencyObject)
Do While dep IsNot Nothing AndAlso Not TypeOf (dep) Is ListViewItem
dep = VisualTreeHelper.GetParent(dep)
Loop
If dep Is Nothing Then
Return -1
Else
Dim lv As ListView = TryCast(sender, ListView)
If lv IsNot Nothing Then
Dim i As Integer = lv.ItemContainerGenerator.IndexFromContainer(dep)
Return i
Else
Return -1
End If
End If
End Function
private bool _ignoreSelectionFlag = false;
private void LbHistory_OnSelectionChanged(object sender,SelectionChangedEventArgs e)
{
if (_ignoreSelectionFlag)
return;
if (e.AddedItems.Count > 0)
{
ListBox listBox = sender as ListBox;
var valid = e.AddedItems[0];
_ignoreSelectionFlag = true;
LbHistory.UnselectAll();
LbHistory.SelectedItems.Add(e.AddedItems[0]);
e.Handled = true;
_ignoreSelectionFlag = false;
}
}