单击WPF ToggleButton会更改其他ToggleButtons值
本文关键字:其他 ToggleButtons WPF ToggleButton 单击 | 更新日期: 2023-09-27 18:02:44
我有一个简单的ToggleButton样式触发器来改变按钮的图像基于IsChecked状态。这是一个很好的工作按钮。但是,当我向网格中添加多个按钮时,单击其中一个ToggleButtons会改变其他按钮的状态。我是否应该使用其他类型的触发器而不是基于按钮样式的触发器?
下面是放置三个ToggleButtons的xaml块:
<Grid Height="362" Width="259">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<ToggleButton Style="{StaticResource TogglebuttonStyle}" IsChecked="{x:Null}" IsThreeState="True"
Width="15" Height="15" Grid.Row="0" Grid.Column="0"/>
<ToggleButton Style="{StaticResource TogglebuttonStyle}" IsChecked="{x:Null}" IsThreeState="True"
Width="15" Height="15" Grid.Row="1" Grid.Column="0"/>
<ToggleButton Style="{StaticResource TogglebuttonStyle}" IsChecked="{x:Null}" IsThreeState="True"
Width="15" Height="15" Grid.Row="2" Grid.Column="0"/>
</Grid>
下面是带有触发器的样式:
<Style x:Key="TogglebuttonStyle" TargetType="ToggleButton">
<Style.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Content">
<Setter.Value>
<Image Source="{StaticResource ImagePlus}"/>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsChecked" Value="False">
<Setter Property="Content">
<Setter.Value>
<Image Source="{StaticResource ImageMinus}"/>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsChecked" Value="{x:Null}">
<Setter Property="Content">
<Setter.Value>
<Image Source="{StaticResource ImageNeutral}"/>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
我将把这称为一个变通方法,但是现在每个按钮都保留了自己的状态:
我发现如果我将Style块移出App.xaml(在标签内)并为每个按钮定义样式触发器,问题行为就会消失。由于我对WPF/XAML相当陌生,所以我不确定这是一个实际的解决方案还是一个黑客的变通方法。这样说明似乎是多余的。
<ToggleButton IsChecked="True" IsThreeState="True"
Width="25" Height="25" Grid.Row="2" Margin="-1,19,1,-19">
<ToggleButton.Style>
<Style TargetType="ToggleButton">
<Style.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Content">
<Setter.Value>
<Image Source="{StaticResource ImagePlus}"/>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsChecked" Value="False">
<Setter Property="Content">
<Setter.Value>
<Image Source="{StaticResource ImageMinus}"/>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsChecked" Value="{x:Null}">
<Setter Property="Content">
<Setter.Value>
<Image Source="{StaticResource ImageNeutral}"/>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
</ToggleButton.Style>
</ToggleButton>
在做了更多的研究之后,我发现我必须指定不能共享样式。
<Style x:Key="ToggleButtonStyle" x:Shared="False" /Style>
问题是setter实例化了Image
控件的一个实例,该控件只能有一个父控件。当按钮进入"ImagePlus"状态时,一切正常。当第二个按钮进入该状态时,该Image
控件被移动到新的父控件,留下旧的控件。
这是XAML有模板的原因之一:当模板被实例化时,该可视树片段的一个新实例被实例化。很快,就没有分享问题了。
对于某些资源,您可以在资源上设置x:Shared="False"
并解决此问题。我在这里找不到一种方法来实现它(我还没有弄清楚它什么时候起作用,什么时候不起作用的原理)。所以我用DataTemplates代替:
<Style x:Key="TogglebuttonStyle" TargetType="ToggleButton" BasedOn="{StaticResource {x:Type ToggleButton}}">
<Style.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Image Source="{StaticResource ImagePlus}" />
</DataTemplate>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsChecked" Value="False">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Image Source="{StaticResource ImageMinus}" />
</DataTemplate>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsChecked" Value="{x:Null}">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Image Source="{StaticResource ImageNeutral}" />
</DataTemplate>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>