【发布时间】: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 创建了一个虚拟类,并使用了您发布的所有代码,它按预期工作。其他地方肯定发生了什么事。
-
非常感谢本和肯特。我休假了一段时间,这得等。
标签: wpf data-binding listbox selecteditem two-way-binding