ListBox TwoWay 绑定到 SelectedItem

Posted

技术标签:

【中文标题】ListBox TwoWay 绑定到 SelectedItem【英文标题】:ListBox TwoWay bind to SelectedItem 【发布时间】:2010-12-26 22:00:13 【问题描述】:

我已经多次看到这个问题被问到,并且一遍又一遍地检查了我的代码。但是当我用一个对象分配给我的SelectedItem-bound 属性时,它不会更新显示的选定项。 ListBox 似乎认为我分配的对象不是其项目的成员。

public class MainViewModel : ViewModelBase

    //...
    public SortedObservableCollection<TubeViewModel> Items  get; private set; 
    public TubeViewModel SelectedTube  //get, set, propertychanged, etc. 


<ListBox x:Name="TubeList"
         Margin="10"
         ItemsSource="Binding Items"
         ItemTemplate="StaticResource TubeTemplate"
         SelectedItem="Binding SelectedTube, Mode=TwoWay" 
         SelectionMode="Single"
         VirtualizingStackPanel.IsVirtualizing="False">
</ListBox>

这是我尝试设置 SelectedTube 的地方之一的 impl - 肯定发生在主线程上。

 var match =
    from t in Items
    where t.Model.DataFileName == filename
    select t;
 if (match.Any())
    SelectedTube = match.First();

我注意到SelectedTube 从未突出显示,除非我手动单击它,但有点忽略了它。但是后来我想ScrollIntoViewCentered选中的项目,所以我在我的视图中添加了一个DependencyProperty来观察SelectedItem的变化。处理程序最初看起来像这样:

private void OnSelectedItemChanged(DependencyObject target, DependencyPropertyChangedEventArgs e)

    if (TubeList.SelectedItem == null)
       return;

    TubeList.ScrollIntoViewCentered(TubeList.SelectedItem);

但如果我通过绑定设置 SelectedItem 则不起作用。在决定我只想滚动它不在屏幕上时,我将代码更改为:

private void OnSelectedItemChanged(DependencyObject target, DependencyPropertyChangedEventArgs e)

    if (TubeList.SelectedItem == null)
       return;

    var container = TubeList.ItemContainerGenerator.ContainerFromItem(TubeList.SelectedItem) as FrameworkElement;

    if(!container.IsVisible)
       TubeList.ScrollIntoViewCentered(TubeList.SelectedItem);

如果SelectedItem 是外部设置的,则容器为空。每次。我什至添加了代码来检查 null,然后遍历 ItemsSource 寻找文件名匹配,然后更新 SelectedItem 以确保 SelectedItem 绝对是列表框中的对象。没有运气。

这不是可见性的事情,如果项目在屏幕上,它仍然不会突出显示。我需要实现某种平等功能吗?我在这方面浪费的时间比人们想象的要多。

谢谢。

【问题讨论】:

我无法用我们看到的您的代码来重现这一点。我为 TubeViewModel 创建了一个虚拟类,并使用了您发布的所有代码,它按预期工作。其他地方肯定发生了什么事。 非常感谢本和肯特。我休假了一段时间,这得等。 【参考方案1】:

也许这也与ItemContainerGenerators是在单独的线程中生成的事实有关......(at least in the TreeView)

在询问 ItemContainerGenerators 属性之前尝试调用 UpdateLayout()。

【讨论】:

我不明白为什么这是必要的,但我很高兴它是。非常感谢。【参考方案2】:

我没有什么明显的错误,但你已经掩饰了很多。我只能建议你简化一些事情,直到你找到问题,或者有一个完整的非工作示例可以发布。

【讨论】:

【参考方案3】:

您是否尝试检查 itemsource 中每个对象的哈希码与您尝试设置的对象的哈希码? Linq 查询将返回不同的内容。

作为尝试将 SelectedTube 设置为 Items[0] 的测试。

【讨论】:

以上是关于ListBox TwoWay 绑定到 SelectedItem的主要内容,如果未能解决你的问题,请参考以下文章

TwoWay 绑定不是真的 Two Way 吗?

WPF日常笔记

如何使用 TwoWay 模式将 Listview SelectedItem 绑定到文本框?

双向绑定到 WPF 中多个列表框上的 ListBox SelectedItem

Silverlight Treeview SelectedItem TwoWay 绑定导致混合错误

TwoWay 模式的绑定和 x:Bind 问题