【发布时间】:2017-12-11 18:24:05
【问题描述】:
我在 WPF 项目中有以下内容:
主窗口
<Window x:Class="DataTemplateEventTesting.Views.MainWindow"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
...
xmlns:vm="clr-namespace:DataTemplateEventTesting.ViewModels"
xmlns:vw="clr-namespace:DataTemplateEventTesting.Views">
<Window.DataContext>
<vm:MainWindowViewModel />
</Window.DataContext>
<Grid>
<Grid.ColumnDefinitions> ... </Grid.ColumnDefinitions>
<ListView ItemsSource="{Binding SubViewModels}"
SelectedValue="{Binding MainContent, Mode=TwoWay}">
<ListView.ItemTemplate>
<DataTemplate DataType="{x:Type vm:SubViewModel}">
<TextBlock Text="{Binding DisplayText}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<ContentControl Grid.Column="1" Content="{Binding MainContent}">
<ContentControl.Resources>
<DataTemplate x:Shared="False" DataType="{x:Type vm:SubViewModel}">
<vw:SubView />
</DataTemplate>
</ContentControl.Resources>
</ContentControl>
</Grid>
</Window>
SubView(SubViewModel 的视图)
<UserControl x:Class="DataTemplateEventTesting.Views.SubView"
...
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity">
<Grid>
<ListView ItemsSource="{Binding Models}">
<ListView.View> ... </ListView.View>
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<i:InvokeCommandAction CommandParameter="{Binding RelativeSource={RelativeSource AncestorType={x:Type ListView}}}"
Command="{Binding PrintCurrentItemsCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</ListView>
</Grid>
</UserControl>
问题在于SubView 中的SelectionChanged EventTrigger。
PrintCurrentItemsCommand 接受 ListView 作为参数并通过执行以下方法打印其项目的计数:
private void PrintCurrentItems(ListView listView)
{
System.Diagnostics.Debug.WriteLine("{0}: {1} items.", DisplayText, listView.Items.Count);
}
当我从一个SubView(其中ListView 中的某些项目被选中)导航到另一个SubView 时,SelectionChanged 事件在第一个SubView 的ListView 上触发。这将在正确的SubViewModel 上执行PrintCurrentItemsCommand,但将新的(不正确的)ListView 作为参数传递。 (要么,要么事件被新的ListView 触发,并且命令使用旧的ListView 中的DataContext。)
因此,虽然“Sub1”的 SubViewModel 和 DisplayText 在其 Models 集合中有 2 个项目,而“Sub2”有 3 个项目,但我在“输出”窗口中看到以下内容:
Sub1: 2 items. // selected an item
Sub1: 3 items. // navigated to Sub2
Sub2: 3 items. // selected an item
Sub2: 2 items. // navigated to Sub1
Sub1: 2 items. // selected an item
Sub1: 3 items. // navigated to Sub2
Sub2: 3 items. // selected an item
Sub2: 2 items. // navigated to Sub1
显然,预期的行为是传递正确的ListView。
主要的困惑是,例如,“Sub1”的命令完全能够访问“Sub2”的ListView。
我阅读了一些关于WPF caching templates 的内容,并认为我已经在DataTemplate 上设置x:Shared = "False" 找到了解决方案,但这并没有改变任何东西。
对这种行为有解释吗?有没有办法解决它?
【问题讨论】:
-
“这会在正确的 SubViewModel 上执行 PrintCurrentItemsCommand” -- 你能详细说明你是如何确认的吗?
-
这是基于为该 ViewModel 打印
DisplayText的方法。我想可能是相反的情况,新的ListView触发了事件,而命令使用的是旧ListView中的DataContext。我会将其添加到问题中。但无论哪种方式,在我看来,“输出”窗口都在确认存在错位。
标签: c# wpf xaml mvvm datatemplate