如何确保数据绑定的ListBox中没有任何项被选中?

4

好的,这可能是一个重复的问题,但我找不到答案:我有一个绑定到 Collection 的列表框。默认情况下,Items[0] 被选择。如何防止这种情况,以确保每次单击 ListBoxItem 时都会引发 SelectionChanged 事件?

编辑: 我已经放弃了 SelectedIndex=-1 的方法,但我再试一次:在 Listbox 的构造函数中(或作为 XAML 属性)将 SelectedIndex 设置为 -1 不起作用。似乎列表框在初始化后被填充,并且选定索引将在所有内容之后成为 0。SelectedItem 设置为 null 的情况同样。

我尝试过这个:

<ListBox ItemsSource="{Binding Value}" 
         SelectionChanged="ListBox_SelectionChanged"
         IsSynchronizedWithCurrentItem="True"
         Loaded="ListBox_Loaded">
</ListBox>

使用:

 private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        if(e.AddedItems.Count==0)return;//Prevents stackoverflow! ;-)
        ((ListBox)e.OriginalSource).SelectedItem=null;
    }

private void ListBox_Loaded(object sender, RoutedEventArgs e)
{
    ((ListBox) sender).SelectedItem = null;
}

这个方法可以解决问题,但会在列表框显示的项目上方插入一个空行,非常难看... 在我的情况下,我可以通过删除IsSynchronizedWithCurrentItem属性来解决这个问题。
但是我可以想到很多场景下这是不可接受的。
以上陈述是无意义的:你要么想利用主从绑定并将IsSynchronizedWithCurrentItem设置为true,要么不想。很不可能你想利用主从绑定,然后在你的列表框中始终没有当前选定的项目。
7个回答

6
在运行了几个测试后,ListBox的默认行为是不会预选列表中的任何一项。移除IsSynchronizedWithCurrentItem="True"将确保ListBox不会开始预选,当用户单击任何项时,SelectionChanged事件将被触发。
如果将IsSynchronizedWithCurrentItem设置为true,则selectedIndex始终等于ListBox.Items.CurrentItem或ListBox.Items的索引。由于CurrentItem或CurrentIndex是只读的,因此无法将ListBox.Items设置为-1或null。
希望这有所帮助。 J
编辑...刚刚阅读到:
“在我的特定情况下,我可以通过删除IsSynchronizedWithCurrentItem属性来解决问题。但我想到了许多情况,这种做法是不可接受的。”
在这种情况下,基于上述原因,我认为这是不可能的。

谢谢,至少它解释了问题的原因! - Dabblernl
谢谢!理解这一点对我来说真的很关键,让我能够解决我们应用程序中的问题。 - CuriousKea

2
listbox.selectedIndex = -1

应该取消选择所有内容(因为索引-1不存在),但据我所知,除非您明确设置默认的selectedItem,否则listview将生成未选择任何内容,因此可能在某些时候无意中设置了SelectedIndex。请注意,SelectedIndex也可以在XAML中设置。


2
使用CollectionView作为ListBox的ItemsSource。一个没有任何项目初始选定的新WPF项目:
XAML:
<Window x:Class="ListBoxDataBinding.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Grid>
    <ListBox 
        ItemsSource="{Binding Path=Value, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}" 
        SelectionChanged="ListBox_SelectionChanged"
        IsSynchronizedWithCurrentItem="True"
        >
    </ListBox>
</Grid>
</Window>

cs:

public partial class Window1: Window {
    public IEnumerable Value {
        get { return (IEnumerable)GetValue(ValueProperty); }
        set { SetValue(ValueProperty, value); }
    }

    public static readonly DependencyProperty ValueProperty =
        DependencyProperty.Register("Value", typeof(IEnumerable), typeof(Window1), new UIPropertyMetadata(null));


    public Window1() {
        InitializeComponent();
        var view = new TheCollectionView();
        view.MoveCurrentTo(null);
        this.Value = view;
    }

    private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e) {
        MessageBox.Show("Selection changed");
    }
}

public class TheCollectionView: CollectionView {
    public TheCollectionView(): base(new TheCollection()) {
    }
}

public class TheCollection: List<string> {
    public TheCollection() {
        Add("string1");
        Add("string2");
        Add("string3");
    }
}

非常好,这段代码展示了一些我不熟悉的方法。谢谢! - Dabblernl
抱歉代码有点乱 - 这只是一个快速而简单的演示解决方案。代码本身在许多方面都是错误的。 - Stanislav Kniazev

1

你需要将 Index 设置为 -1,这会告诉列表框不选中任何内容。在 SelectionChanged 事件中,将列表框的 Index 属性设置为 -1。

希望能对你有所帮助, 祝好, Tom。


1

考虑放弃SelectionChanged事件处理程序,改为数据绑定依赖属性或通知属性到SelectedValue上如何?


那是一个有趣的练习,但基本上并没有改变行为。此外,在视图模型的 PropertyChangedCallBack 中将 SelectedValue 设置为 null 不再起作用,似乎无论如何都会选择点击的项目。 - Dabblernl

1

只需进入列表框的属性。选择数据选项卡,然后选择绑定列。输入-1,此条目将自动更改为65535。

接下来将允许值列表编辑属性更改为“否”。最后将锁定属性更改为“否”。

现在您的用户无法选择列表中的项目,并且避免了项目上的反向视频。


0
你可以使用Tap事件而不是SelectionChanged:
<ListBox  ItemsSource="{Binding Data}" Tap="ListBox_Tap" ... />

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接