Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/dart/3.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
Wpf 列表框,单击时选择并取消选择。。。?_Wpf_Xaml_Listbox_Selection_Listboxitem - Fatal编程技术网

Wpf 列表框,单击时选择并取消选择。。。?

Wpf 列表框,单击时选择并取消选择。。。?,wpf,xaml,listbox,selection,listboxitem,Wpf,Xaml,Listbox,Selection,Listboxitem,我需要一个列表框,在第一次单击时选择,在第二次单击时取消选择,以便在任何时候只选择零个或一个项目 按住crtl键时,选择/取消选择在列表框中实现(使用SelectionMode=“Single”),但不幸的是,我的用户都不知道这一点 使用SelectionMode=“Multiple”我们拥有我想要的确切功能,只是您可以选择多个项目 更多背景: 我希望用户首先选择要登录的安装,然后提供凭据(以及其他一些选择) 为了实现这一点,我使用了一个扩展内容的列表框。为了帮助展开,我在listboxitem

我需要一个列表框,在第一次单击时选择,在第二次单击时取消选择,以便在任何时候只选择零个或一个项目

按住crtl键时,选择/取消选择在列表框中实现(使用SelectionMode=“Single”),但不幸的是,我的用户都不知道这一点

使用SelectionMode=“Multiple”我们拥有我想要的确切功能,只是您可以选择多个项目

更多背景: 我希望用户首先选择要登录的安装,然后提供凭据(以及其他一些选择)

为了实现这一点,我使用了一个扩展内容的列表框。为了帮助展开,我在listboxitem左侧制作了一个三角形,未展开时指向右侧,选中listboxitem时指向下方

因此,首先用户在安装上看到列表,然后,当用户通过选择来选择他想要的项目时,listboxitem将扩展到他需要输入的其余信息。这很好,工作也很好,但测试报告显示,他们希望再次单击三角形以取消选择(从而折叠展开的部分)。我必须承认,我也单击了·%&箭头,期望该操作会导致崩溃…:-(

任何人都知道如何实现这一点(最好没有代码隐藏)?

试试:

您可以使用切换按钮作为详细内容的“扩展器”。 切换按钮的“IsChecked”属性可以绑定到项的IsSelected属性

代码如下:

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


        }
    }