我有一个WPF应用程序,当用户按下按钮时,ListBox的内容就会更新。我最初的问题是将ListBox重新聚焦到特定的SelectedIndex值,该值绑定到ViewModel中的ActiveItem属性。我可以使用以下代码解决此问题:
XAML:
flush_in(stdin)
隐藏代码:
<ListBox ItemsSource="{Binding ListOfItems}" SelectedIndex="{Binding ActiveItem, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
IsSynchronizedWithCurrentItem="True" SelectionChanged="ListBox_SelectionChanged" x:Name="ListBoxSelector">
但是,我目前在MainWindow.xaml.cs文件而不是ViewModel中具有以上代码。我的问题是如何将这段代码移至ViewModel,以便坚持使用MVVM模式?我不太清楚如何从ViewModel中正确处理ListBox的ScrollIntoView属性。
答案 0 :(得分:1)
您可以使用Behavior
类强制选定的项目滚动到视图中。
public class perListBoxHelper : Behavior<ListBox>
{
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.SelectionChanged += AssociatedObject_SelectionChanged;
}
protected override void OnDetaching()
{
AssociatedObject.SelectionChanged -= AssociatedObject_SelectionChanged;
base.OnDetaching();
}
private static void AssociatedObject_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var listBox = sender as ListBox;
if (listBox?.SelectedItem == null)
return;
Action action = () =>
{
listBox.UpdateLayout();
if (listBox.SelectedItem != null)
listBox.ScrollIntoView(listBox.SelectedItem);
};
listBox.Dispatcher.BeginInvoke(action, DispatcherPriority.ContextIdle);
}
}
有关我的blog post的更多详细信息。
此外,我个人将绑定到ListBox的SelectedItem
而不是SelectedIndex
,并在该属性设置器中处理对项目选择的任何处理,而不是使用事件处理程序。
答案 1 :(得分:0)
MVVM模式不排除使用后面的代码。实际上,这不可能,因为在某些情况下,背后的代码是正确的做法。视图模型是一个模型,不是视图替换。考虑它的另一种方法是,视图模型包含内容,而视图包含方式。至少,这是我对MVVM模式的解释。
在您的情况下,什么是项目列表和当前项目。 how 是ListBox
本身及其默认行为。在我看来,将选定的项目滚动到视图中是一种额外的行为,因此应保留在视图中。您不会违反MVVM模式,因为您将内容保留在视图模型中,并将 how 保留在视图中。
答案 2 :(得分:0)
我不确定我的解决方案是否是MVVM模式。但是对于这种问题,它可以解决此问题。
这是我要做的:如果按下Button,它将触发一个命令调用ViewModel中的方法。当ViewModel完成其工作时,viewModel会引发一个自定义事件(其中包括项目索引,列表框应滚动到该事件)。并且在发生这种情况之前,加载View时,View的Code-behind应该通过View的DataContext侦听其ViewModel,然后执行scrollIntoView。
正如我所说,我不确定这是否是MVVM,但是我认为这是可以接受的。
答案 3 :(得分:0)
没有针对每个请求的通用解决方案,正如其他人提到的那样,MVVM并不意味着没有代码,但也没有多余的代码。
但是,如果您不想要任何代码,则可以在您的特定请求中找到解决方案-创建一个继承自ListView
的类并按需要处理请求,然后在XAML中使用它。 / p>