【发布时间】:2018-01-28 19:46:30
【问题描述】:
我在 WPF 表单上有用于显示布尔值的切换按钮。
其中一些按钮应该是“只读”的,所以我将它们设置为 IsEnabled = false。
然而,那些应该显示它们的 IsChecked 状态,但它们都显示为未选中
如您所见,所有禁用的似乎都未选中,其中一些应该被选中。
我正在通过代码创建切换按钮,但“静态”切换按钮也存在问题
ToggleButton tb = new ToggleButton();
tb.Name = "btnRegisterR" + register + "P" + pos;
tb.Content = tuple.Item1";
tb.IsChecked = rnd.NextDouble() >= 0.5;
tb.IsEnabled = tuple.Item2;
tb.VerticalAlignment = VerticalAlignment.Top;
tb.HorizontalAlignment = HorizontalAlignment.Left;
tb.Height = 25;
tb.Width = 87;
tb.Margin = new Thickness(xPos, yPos, 0, 0);
registerGrid.Children.Add(tb);
编辑:我不认为这是链接问题的重复,因为我并不想禁用按钮上的交互,而是让它看起来被禁用但继续显示它状态。链接的问题仅回答功能部分,而我主要询问的是样式部分。
例如,在 Winforms 中,有一个复选框的外观按钮,它允许 2 种单独的显示状态(默认情况下,未选中/未选中时为灰色按钮,选中/选中时为浅蓝色按钮)。
除此之外,还可以启用/禁用控件,在禁用状态下,这会使整个控件变白,但在启用或禁用时仍会以不同的方式显示。
编辑 2 :为了进一步说明,这是我在旧的 Winform 应用程序中使用的,其中复选框的外观设置设置为“按钮”
您可以清楚地在视觉上区分启用或禁用的那些,同时仍然能够看到输入的状态(选中或未选中)。我只是想在 WPF 中复制这种显示行为,暂时没有成功,因为“Checked|Disabled”和“Unchecked|Disabled”看起来与 WPF 切换按钮完全相同。
编辑 3:
我最终在样式中使用了多触发器来使其工作。不知道这是否是最好的解决方案,但至少它给出了与 winform 中相同的结果
<Style x:Key="FocusVisual">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<Rectangle Margin="2" SnapsToDevicePixels="true" Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" StrokeThickness="1" StrokeDashArray="1 2"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<SolidColorBrush x:Key="Button.Static.Background" Color="#FFDDDDDD"/>
<SolidColorBrush x:Key="Button.Static.Border" Color="#FF707070"/>
<SolidColorBrush x:Key="Button.MouseOver.Background" Color="#FFBEE6FD"/>
<SolidColorBrush x:Key="Button.MouseOver.Border" Color="#FF3C7FB1"/>
<SolidColorBrush x:Key="Button.Pressed.Background" Color="#FFC4E5F6"/>
<SolidColorBrush x:Key="Button.Pressed.Border" Color="#FF2C628B"/>
<SolidColorBrush x:Key="Button.Disabled.Background" Color="#FFF4F4F4"/>
<SolidColorBrush x:Key="Button.Disabled.Border" Color="#FFADB2B5"/>
<SolidColorBrush x:Key="Button.Disabled.Foreground" Color="#FF838383"/>
<Style x:Key="disabledAndCheckedButton" TargetType="{x:Type ToggleButton}">
<Setter Property="FocusVisualStyle" Value="{StaticResource FocusVisual}"/>
<Setter Property="Background" Value="{StaticResource Button.Static.Background}"/>
<Setter Property="BorderBrush" Value="{StaticResource Button.Static.Border}"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Padding" Value="1"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="true">
<ContentPresenter x:Name="contentPresenter" Focusable="False" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="Button.IsDefaulted" Value="true">
<Setter Property="BorderBrush" TargetName="border" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Background" TargetName="border" Value="{StaticResource Button.MouseOver.Background}"/>
<Setter Property="BorderBrush" TargetName="border" Value="{StaticResource Button.MouseOver.Border}"/>
</Trigger>
<Trigger Property="IsChecked" Value="true">
<Setter Property="Background" TargetName="border" Value="{StaticResource Button.Pressed.Background}"/>
<Setter Property="BorderBrush" TargetName="border" Value="{StaticResource Button.Pressed.Border}"/>
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsChecked" Value="False" />
<Condition Property="IsEnabled" Value="False" />
</MultiTrigger.Conditions>
<MultiTrigger.Setters>
<Setter Property="Background" TargetName="border" Value="{StaticResource Button.Disabled.Background}"/>
<Setter Property="BorderBrush" TargetName="border" Value="{StaticResource Button.Disabled.Border}"/>
<Setter Property="TextElement.Foreground" TargetName="contentPresenter" Value="{StaticResource Button.Disabled.Foreground}"/>
</MultiTrigger.Setters>
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsChecked" Value="True" />
<Condition Property="IsEnabled" Value="False" />
</MultiTrigger.Conditions>
<MultiTrigger.Setters>
<Setter Property="TextElement.Foreground" TargetName="contentPresenter" Value="{StaticResource Button.Disabled.Foreground}"/>
</MultiTrigger.Setters>
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
【问题讨论】:
-
我不认为我的问题是重复的,有关详细信息,请参阅我的编辑。
-
“我并不想禁用按钮上的交互,而是让它看起来被禁用但继续显示它的状态”——这至少没有意义两个原因:首先,为什么你想要一个没有被禁用的按钮,看起来被禁用了?您是否故意试图混淆您的用户?其次,“看起来已禁用” 与 “显示其 [原文如此] 状态” 完全相反。禁用的“外观”是一种特定外观,它不 显示您似乎想要的颜色。请修正您的问题,以便了解您真正想要的是什么。
-
最重要的是,您应该使用 XAML 而不是代码隐藏来创建您的 UI,您可以在其中编辑控件模板,使其看起来与您完全一样在任何情况下都想要。
-
@PeterDuniho :我完全希望禁用我的禁用按钮,但我不希望它在禁用时不显示它的选中状态。当我说状态时,我说的是它的“IsChecked”属性,很抱歉造成误解。我同意尽可能在 XAML 中定义控件,但这里它们是从运行时读取的配置文件生成的,因此我必须通过代码创建它们。我添加了一个编辑来阐明我希望在 WPF 中重现的状态。
标签: c# wpf user-interface togglebutton