如何通过触发器/行为修改WinUI中Image控件的源?
如何通过触发器/行为修改WinUI中Image控件的源?
你现在遇到的问题我完全理解:在WinUI的DataTemplate里有两个Image控件,想根据Model的Type属性(值为Case1或Case2),把TypeImageUri绑定到对应的Image上,之前用Interactivity的DataTriggerBehavior没成功,而且不想用后台代码实现,对吧?
先给你说下为什么之前的写法不行:你在ChangePropertyAction里用Value="{x:Bind TypeImageUri}"是无效的,因为Value属性不是依赖属性,XAML解析器不会处理这个绑定表达式,只会把它当成普通字符串,所以Image的Source会被设置成字符串"{x:Bind TypeImageUri}",而不是实际的图片Uri。
下面给你几个纯XAML的可行方案,你可以根据自己的习惯选择:
方案1:用Style的DataTrigger(轻量无依赖)
这种方法不需要额外引用Behaviors库,是WinUI原生支持的,逻辑也清晰:
<DataTemplate x:DataType="MyModel"> <Grid> <Image x:Name="Image1" Grid.Row="0" Grid.Column="1" Height="16"> <Image.Style> <Style TargetType="Image"> <!-- 默认绑定图片,当Type是Case2时清空 --> <Setter Property="Source" Value="{x:Bind TypeImageUri}" /> <Style.Triggers> <DataTrigger Binding="{x:Bind Type}" Value="Case2"> <Setter Property="Source" Value="{x:Bind x:Null}" /> </DataTrigger> </Style.Triggers> </Style> </Image.Style> </Image> <Image x:Name="Image2" Grid.Row="1" Grid.Column="1" Height="16"> <Image.Style> <Style TargetType="Image"> <!-- 默认空,当Type是Case2时绑定图片 --> <Setter Property="Source" Value="{x:Bind x:Null}" /> <Style.Triggers> <DataTrigger Binding="{x:Bind Type}" Value="Case2"> <Setter Property="Source" Value="{x:Bind TypeImageUri}" /> </DataTrigger> </Style.Triggers> </Style> </Image.Style> </Image> </Grid> </DataTemplate>
方案2:修复Behaviors的写法(如果你一定要用Behaviors)
如果你坚持要用Microsoft.Xaml.Behaviors.WinUI.Managed的话,可以这样修改,把Source的绑定通过BitmapImage来传递:
<DataTemplate x:DataType="MyModel"> <Grid> <Image x:Name="Image1" Grid.Row="0" Grid.Column="1" Height="16" Source="{x:Bind x:Null}" /> <Image x:Name="Image2" Grid.Row="1" Grid.Column="1" Height="16" Source="{x:Bind x:Null}" /> <interactivity:Interaction.Behaviors> <!-- Case1时给Image1设置图片 --> <interactivity:DataTriggerBehavior Binding="{x:Bind Type}" ComparisonCondition="Equal" Value="Case1"> <interactivity:ChangePropertyAction TargetObject="{Binding ElementName=Image1}" PropertyName="Source"> <interactivity:ChangePropertyAction.Value> <BitmapImage UriSource="{x:Bind TypeImageUri}" /> </interactivity:ChangePropertyAction.Value> </interactivity:ChangePropertyAction> </interactivity:DataTriggerBehavior> <!-- Case2时给Image2设置图片 --> <interactivity:DataTriggerBehavior Binding="{x:Bind Type}" ComparisonCondition="Equal" Value="Case2"> <interactivity:ChangePropertyAction TargetObject="{Binding ElementName=Image2}" PropertyName="Source"> <interactivity:ChangePropertyAction.Value> <BitmapImage UriSource="{x:Bind TypeImageUri}" /> </interactivity:ChangePropertyAction.Value> </interactivity:ChangePropertyAction> </interactivity:DataTriggerBehavior> </interactivity:Interaction.Behaviors> </Grid> </DataTemplate>
这里通过直接创建BitmapImage并绑定UriSource,就能正确把图片Uri传递给Image的Source属性了。
方案3:用VisualStateManager(WinUI推荐方式)
这是WinUI官方更推荐的状态管理方式,逻辑清晰,扩展性强:
<DataTemplate x:DataType="MyModel"> <Grid> <VisualStateManager.VisualStateGroups> <VisualStateGroup x:Name="TypeStates"> <VisualState x:Name="Case1State"> <VisualState.StateTriggers> <!-- 当Type等于Case1时激活这个状态 --> <StateTrigger IsActive="{x:Bind Type == 'Case1', Mode=OneWay}" /> </VisualState.StateTriggers> <VisualState.Setters> <Setter Target="Image1.Source" Value="{x:Bind TypeImageUri}" /> <Setter Target="Image2.Source" Value="{x:Bind x:Null}" /> </VisualState.Setters> </VisualState> <VisualState x:Name="Case2State"> <VisualState.StateTriggers> <!-- 当Type等于Case2时激活这个状态 --> <StateTrigger IsActive="{x:Bind Type == 'Case2', Mode=OneWay}" /> </VisualState.StateTriggers> <VisualState.Setters> <Setter Target="Image1.Source" Value="{x:Bind x:Null}" /> <Setter Target="Image2.Source" Value="{x:Bind TypeImageUri}" /> </VisualState.Setters> </VisualState> </VisualStateGroup> </VisualStateManager.VisualStateGroups> <Image x:Name="Image1" Grid.Row="0" Grid.Column="1" Height="16" /> <Image x:Name="Image2" Grid.Row="1" Grid.Column="1" Height="16" /> </Grid> </DataTemplate>
这种方式可以很方便地扩展更多状态,比如以后加Case3的话,只需要新增一个VisualState就行。
备注:内容来源于stack exchange,提问作者xerxos
相关产品推荐
相关产品推荐

