问题描述:MVVMLight框架中,改写ListBox、ListBox.ItemTemplate模板时,模板里面的Button/Image控件绑定命令后,触发不起作用,但在ListBox外的命令正常绑定到指定的ViewModel;
VieweModel 为CarPicturesViewModel,绑定上下文DataContext="{Binding CarPicturesVM ,Source={StaticResource Locator}}"
问题代码:
1.声明绑定数据类CarInfo
public class CarInfo : BaseNotifyProperty
{
private int carIndex;
public int CarIndex
{
get { return carIndex; }
set
{
carIndex = value;
OnPropertyChanged("CarIndex");
}
}
private string carName;
public string CarName
{
get { return carName; }
set
{
carName = value;
OnPropertyChanged("CarName");
}
}
}
2.界面设计代码,整个界面是UserControl
<UserControl x:Class="CarRental.View.CarPicturesView"
DataContext="{Binding CarPicturesVM ,Source={StaticResource Locator}}">
<Grid>
<ListBox x:Name="listboxImages" HorizontalAlignment="Left" VerticalAlignment="Top" Width="1780" Height="870" ItemsSource="{Binding DisplayImageList}">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Top" Background="Transparent"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate x:Name="gridDataTemplate">
<Border x:Name="DataTemplateBr" CornerRadius="5" HorizontalAlignment="Left" BorderThickness="2" VerticalAlignment="Top">
<Border.Background>
<ImageBrush ImageSource="Pack://application:,,,/CarRental;component/Images/CarInfo/white.png" Opacity="0.32">
</ImageBrush>
</Border.Background>
<Grid Margin="5" Height="400" Width="250">
<Button Command="{Binding AddImageRecord}" />
<Grid Visibility="{Binding IsShowAddImage,Converter={StaticResource boolToNVisibilityConverter}}">
<Grid.RowDefinitions>
<RowDefinition Height="250"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<Image x:Name="image_Check" Grid.Row="0" Margin="5" Height="30" Width="30" HorizontalAlignment="Left" VerticalAlignment="Top" Panel.ZIndex="9999" >
<Image.Style>
<Style TargetType="{x:Type Image}">
<Setter Property="Source" Value="Pack://application:,,,/CarRental;component/Images/CarInfo/check.png"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Source" Value="/CarRental;component/Images/CarInfo/check_sel.png"/>
</Trigger>
</Style.Triggers>
</Style>
</Image.Style>
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseDown">
<i:InvokeCommandAction Command="{Binding AddRentalRecord}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Image>
<StackPanel Margin="0,5,0,0" Grid.Row="1">
<Grid>
<TextBlock Margin="0,5,0,0" Text="名称:" Style="{StaticResource txtblock}"/>
<TextBlock Margin="45,5,0,0" Text="{Binding CarName}" Style="{StaticResource txtblock}" Width="200"/>
</Grid>
</StackPanel>
</Grid>
</Grid>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</UserControl>
问题原因:因为 ListBox 的ItemsSource绑定了 DisplayImageList,DisplayImageList 是一个 CarInfo 类的列表,ListBox里面控件的DataContext就成了CarInfo也就是里面控件的Binding都是CarInfo的属性,比如名称(Binding="{Binding Name}")。而CarInfo里没有AddImageRecord,所以就不能触发操作了。
解决方法:把Button的Command绑定为ViewModel里面的AddImageRecord就好了,而ListBox的DataContext就是ViewModel,那这样做就好了;
解决代码: <Button Command="{Binding CarPicturesVM.AddRentalRecord,Source={StaticResource Locator}}" /> 或者
Command="{Binding DataContext.AddRentalRecord,RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}" 或者
Command="{Binding DataContext.AddRentalRecord,RelativeSource={RelativeSource AncestorLevel=2, AncestorType={x:Type UserControl}}}"
AncestorLevel:模式中获取或设置要查找的上级节点的级别。 使用 1 表示与绑定目标元素最近的一个级别。
返回值:上级节点级别。 使用 1 表示与绑定目标元素最近的一个级别。
AncestorType:获取或设置要查找的上级节点的类型。
修改后正确代码
<UserControl x:Class="CarRental.View.CarPicturesView"
DataContext="{Binding CarPicturesVM ,Source={StaticResource Locator}}">
<Grid>
<ListBox x:Name="listboxImages" HorizontalAlignment="Left" VerticalAlignment="Top" Width="1780" Height="870" ItemsSource="{Binding DisplayImageList}">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Top" Background="Transparent"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate x:Name="gridDataTemplate">
<Border x:Name="DataTemplateBr" CornerRadius="5" HorizontalAlignment="Left" BorderThickness="2" VerticalAlignment="Top">
<Border.Background>
<ImageBrush ImageSource="Pack://application:,,,/CarRental;component/Images/CarInfo/white.png" Opacity="0.32">
</ImageBrush>
</Border.Background>
<Grid Margin="5" Height="400" Width="250">
<Button Command="{Binding DataContext.AddImageRecord,RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}" />
<Grid Visibility="{Binding IsShowAddImage,Converter={StaticResource boolToNVisibilityConverter}}">
<Grid.RowDefinitions>
<RowDefinition Height="250"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<Image x:Name="image_Check" Grid.Row="0" Margin="5" Height="30" Width="30" HorizontalAlignment="Left" VerticalAlignment="Top" Panel.ZIndex="9999" >
<Image.Style>
<Style TargetType="{x:Type Image}">
<Setter Property="Source" Value="Pack://application:,,,/CarRental;component/Images/CarInfo/check.png"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Source" Value="/CarRental;component/Images/CarInfo/check_sel.png"/>
</Trigger>
</Style.Triggers>
</Style>
</Image.Style>
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseDown">
<i:InvokeCommandAction Command="{Binding DataContext.AddRentalRecord,RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Image>
<StackPanel Margin="0,5,0,0" Grid.Row="1">
<Grid>
<TextBlock Margin="0,5,0,0" Text="名称:" Style="{StaticResource txtblock}"/>
<TextBlock Margin="45,5,0,0" Text="{Binding CarName}" Style="{StaticResource txtblock}" Width="200"/>
</Grid>
</StackPanel>
</Grid>
</Grid>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</UserControl>