【发布时间】:2012-01-11 22:16:20
【问题描述】:
我有一个带有列表框的 XAML 视图:
<control:ListBoxScroll ItemSource="{Binding Path=FooCollection}"
SelectedItem="{Binding SelectedFoo, Mode=TwoWay}"
ScrollSelectedItem="{Binding SelectedFoo}">
<!-- data templates, etc. -->
</control:ListBoxScroll>
在我的视图中,选定的项目绑定到一个属性。当用户在列表框中选择一个项目时,我在视图模型中的 SelectedFoo 属性得到更新。当我在视图模型中设置 SelectedFoo 属性时,会在列表框中选择正确的项目。
问题是,如果在代码中设置的 SelectedFoo 当前不可见,我需要在列表框上另外调用 ScrollIntoView。由于我的 ListBox 在视图内,而我的逻辑在我的视图模型内......我找不到方便的方法来做到这一点。于是我扩展了 ListBoxScroll:
class ListBoxScroll : ListBox
{
public static readonly DependencyProperty ScrollSelectedItemProperty = DependencyProperty.Register(
"ScrollSelectedItem",
typeof(object),
typeof(ListBoxScroll),
new FrameworkPropertyMetadata(
null,
FrameworkPropertyMetadataOptions.AffectsRender,
new PropertyChangedCallback(onScrollSelectedChanged)));
public object ScrollSelectedItem
{
get { return (object)GetValue(ScrollSelectedItemProperty); }
set { SetValue(ScrollSelectedItemProperty, value); }
}
private static void onScrollSelectedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var listbox = d as ListBoxScroll;
listbox.ScrollIntoView(e.NewValue);
}
}
它基本上公开了一个新的依赖属性ScrollSelectedItem,我将它绑定到我的视图模型上的SelectedFoo 属性。然后我挂钩到依赖属性的属性更改回调并将新选择的项目滚动到视图中。
还有其他人知道在由视图模型支持的 XAML 视图上调用用户控件上的函数的更简单方法吗?有点跑来跑去:
- 创建依赖属性
- 向属性更改回调添加回调
- 在静态回调中处理函数调用
将逻辑放在ScrollSelectedItem { set { 方法中会很好,但依赖框架似乎偷偷摸摸地在没有实际调用的情况下设法工作。
【问题讨论】:
-
设置
SelectedIndex会容易得多。 -
这听起来像是一个视图“关注”而不是视图模型。我不得不做类似的事情,但我把代码留在了视图中。见matthamilton.net/focus-a-virtualized-listboxitem
-
@MattHamilton - 此代码在技术上位于视图中(在控件内)。你会在 View(任何地方)中编写什么代码来完成调用 ScrollIntoView?请记住,我不能覆盖 SelectedItem 上的集合,因为它不是虚拟的。
-
@anatoliiG - SelectedIndex 是否会导致视图滚动到所选项目?
-
@JamesFassett 对于
DataGrid- 是的。不幸的是,我还没有尝试过ListBox。