ItemsControlItemTemplate绑定选择了错误的视图模型



我重写了这个问题:

使用WPF和caliburn-micro,当调用Select("这个"是错误的(时,我绑定到"Select"方法会选择错误的视图模型

interface Base
{
void Select();
// and more, eg IsSelected, ButtonName
}
class ViewModel : Base
{
List<Base> Items;
void Select()
{
// now this=A which is wrong
}
}
void Run()
{
var A = new ViewModel();
var B = new ViewModel();
A.Items.Add(B);
}

视图包含以下内容:

<ItemsControl ItemsSource="{Binding Items}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<RadioButton Style="{StaticResource RadioButtonSelectorStyle}" GroupName="Main" Content="{Binding ButtonName}" IsChecked="{Binding IsSelected}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<cal:ActionMessage MethodName="Select" />
</i:EventTrigger>
</i:Interaction.Triggers>
</RadioButton>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>

如果您有一个混合或复合集合,在通过设置DataType定义没有类型提示的DataTemplate时,XAML解析器必须推断实际的数据类型。现在,如果被引用的(虚拟(成员是在公共基类或接口中定义的,那么解析器将采用随机匹配实现来解析引用。

如果绑定到属性,则这种行为没有副作用,除非它们被定义为virtual(这种情况很少发生,因为属性不是用来实现行为的,而是用来存储状态(。但是,由于您绑定到一个方法,当每个实现或专门化都提供引用方法的自己的实现时,您会遇到意外的行为。

解决方案是显式定义DataTemplateDataType,尤其是在处理复合集合时
为了动态地建立数据模板,您必须为每个项目类型定义一个DataTemplate。您可以在ItemsControl范围内的ResourceDictionary中定义它们,例如ItemsControl.Resources。由于模板是隐式的(没有键(,它们将自动应用于当前数据类型:

<ItemsControl>
<ItemsControl.Resources>
<DataTemplate DataType="{x:Type RadioButtonViewModel}>
<RadioButton>
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<cal:ActionMessage MethodName="Select" />
</i:EventTrigger>
</i:Interaction.Triggers>
</RadioButton>
</DataTemplate>
<DataTemplate DataType="{x:Type ScreenViewModel}>
<RadioButton>
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<cal:ActionMessage MethodName="Select" />
</i:EventTrigger>
</i:Interaction.Triggers>
</RadioButton>
</DataTemplate>
</ItemsControl.Resources>
</ItemsControl>

最新更新