如何在可导航应用程序中使用MVVM支持ListBox SelectedItems绑定

46

我正在制作一个WPF应用程序,可以通过自定义的“下一步”和“上一步”按钮和命令进行导航(即不使用NavigationWindow)。在一个屏幕上,我有一个需要支持多选(使用Extended模式)的ListBox。我为这个屏幕创建了一个视图模型,并将所选项存储为属性,因为它们需要被保留。

然而,我知道ListBoxSelectedItems属性是只读的。我一直在尝试使用这里的解决方案解决这个问题,但我无法将其纳入我的实现。我发现我无法区分何时取消选择了一个或多个元素,还是当我在屏幕之间导航时(NotifyCollectionChangedAction.Remove在两种情况下都会被引发,因为在导航离开屏幕时,技术上所有所选项目都将被取消选择)。我的导航命令位于一个单独的视图模型中,该视图模型管理每个屏幕的视图模型,因此我不能将与ListBox的视图模型相关的任何实现放在那里。

我发现了其他几个不太优雅的解决方案,但这些解决方案似乎都没有强制执行视图模型和视图之间的双向绑定。

如果有帮助理解我的问题,我可以提供一些源代码。任何帮助都将不胜感激。


1
啊,我明白了,你已经尝试使用行为了。使用BindableCollection来选择项目,它应该可以工作。如果你有更多的问题,就让我知道。描述一下它们,我们会看看的。 - Mare Infinitus
2
请展示一些代码,特别是SelectedItems和XAML。SelectedItems是一个属性吗?怀疑当SelectedItems只是BindableCollection的公共成员而不是属性时会出现这种行为。 - Mare Infinitus
2
啊,我没有意识到属性必须明确地被称为“SelectedItems”(我的被称为“SelectedLanguages”)。现在当我点击“Back”按钮时,在调用RaisePropertyChangedEventHandler的分派程序处,BindableCollection构造函数会抛出一个InvalidOperationException。我尝试在catch块中使用Dispatcher.BeginInvoke放置一个try/catch块,但是当页面导航回来时,列表项不会重新选择。 - kck
这个回答解决了你的问题吗?在MVVM中从DataGrid或ListBox绑定到SelectedItems - StayOnTarget
11个回答

0
如果您只想获取所选元素的名称,可以执行以下操作:
视图:
<ListBox
    x:Name="Folders"
    Grid.Row="1"
    Grid.Column="0"
    ItemsSource="{Binding YourListWithStings}"
    SelectionMode="Single"
    SelectedItem="{Binding ToYourOutputVariable}"
    >
    <ListBox.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="{Binding}"/>
            </StackPanel>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

视图模型:

private string _ToYourOutputVariable
public string ToYourOutputVariable
{
    get {return _ToYourOutputVariable; }
    set 
       {
          _ToYourOutputVariable = value;
          NotifyOfPropertyChange(); 
          MessageBox.Show(_ToYourOutputVariable);
       }
}

messageBox 显示所选列表项的名称。您可以调用一个函数,在其中打开 MessageBox。


我在set{}代码中修正了一个拼写错误。 - StayOnTarget
非常感谢 @StayOnTarget,我没有看到那个。 - user19143260

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接