Tho*_*mas 5 data-binding wpf listbox selecteditem two-way-binding
我已经多次看到这个问题并且一遍又一遍地查看我的代码.但是,当我SelectedItem使用对象分配我的绑定属性时,它不会更新显示的选定项.看来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>
Run Code Online (Sandbox Code Playgroud)
这是我尝试设置的其中一个地方的impl SelectedTube- 肯定发生在主线程上.
var match =
from t in Items
where t.Model.DataFileName == filename
select t;
if (match.Any())
SelectedTube = match.First();
Run Code Online (Sandbox Code Playgroud)
我注意到,SelectedTube除非我手动点击它,否则从未突出显示,但有点忽略它.但后来我想ScrollIntoViewCentered所选项目,所以我DependencyProperty在我的视图中添加了一个观察SelectedItem更改.处理程序最初看起来像这样:
private void OnSelectedItemChanged(DependencyObject target, DependencyPropertyChangedEventArgs e)
{
if (TubeList.SelectedItem == null)
return;
TubeList.ScrollIntoViewCentered(TubeList.SelectedItem);
}
Run Code Online (Sandbox Code Playgroud)
但如果我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);
}
Run Code Online (Sandbox Code Playgroud)
如果SelectedItem是外部设置,则容器为空.每次.我甚至添加了代码来检查null,然后迭代ItemsSource查找文件名匹配,然后更新SelectedItem以确保SelectedItem绝对是列表框中的对象.没运气.
这不是一个可见性的东西,如果项目在屏幕上,它仍然不会突出显示.我需要实现某种平等功能吗?我浪费的时间比人们想象的要多.
谢谢.
也许这也与ItemContainerGenerators在单独的线程中生成的事实有关...(至少在TreeView中)
在询问ItemContainerGenerators酒店之前,请尝试调用UpdateLayout().