【问题标题】:WPF recommended way of switching style for buttonWPF推荐的按钮样式切换方式
【发布时间】:2013-11-27 07:46:34
【问题描述】:

基本上我有两个并排的按钮,并且我定义了两组样式。出于说明目的,styleA 是白色,styleB 是黑色。这个想法应该有点简单,当用户单击buttonA 时,它将应用白色的styleAbuttonB 将应用styleB,反之亦然。然而,经过数小时的研究,没有简单的方法可以实现这一目标吗?有些人建议使用RelativeSource AncestorType,而有些人建议使用Converter。我是否完全偏离了轨道,因为我相信我的目标应该能够轻松完成。请帮忙,因为我是 WPF 领域的新手

【问题讨论】:

  • 逻辑不清楚,能否改写一下?
  • @NicolasRepiquet:很简单,默认情况下有两个按钮应用styleB,因此它们都是黑色的。现在说buttonA 被点击,它将应用styleB 并变成白色,而buttonB 保持黑色。然后,当用户单击buttonB 时,buttonB 将应用styleBbuttonA 应用styleA,结果buttonB 将是白色而buttonA 是黑色
  • 你想达到什么目的? ToggleButton 可能更适合你。

标签: c# wpf


【解决方案1】:

您可以做的是在资源字典中定义两种样式,然后在按钮的单击处理程序或单选按钮的 Selected 处理程序中,动态查找有问题的资源,并将找到的资源(样式)应用于要重新设置样式的元素。

【讨论】:

  • 是的,我认为方向是正确的。您能否提供一些关于如何从事件处理程序中查找资源并将找到的资源应用于元素的简单代码?
  • 看看这里。这将使您朝着正确的方向前进。 msdn.microsoft.com/en-us/library/…。然后将找到的资源转换为 Style。
【解决方案2】:

我认为最简单的方法是使用带有 styleA 的 RadioButtons 和一个触发器,如果​​它被选中,它将获得 styleB。这样,当您单击其中一个按钮时,您将“免费”获得 styleB,而另一个按钮返回 styleA。

【讨论】:

  • 天哪,终于有人明白我想要什么了。是的,行为就像一个单选按钮,但我想将行为应用到一个按钮
  • 为什么不使用RadioButton,让它看起来像一个普通的Button?更改外观比在控件上强制执行不同的行为要容易得多。
  • @IsaacLem 在单选按钮中无法获得的按钮中是否有您需要的特定行为? RadioButton 也有一个 Click 事件。
【解决方案3】:

更简单的方法是只制作一种样式并使用触发器

<Style
  TargetType="{x:Type Button}">
  <Setter Property="Background" Value="#C0C0C0"/>
  <Setter Property="BorderBrush" Value="#404040"/>
  <Setter Property="BorderThickness" Value="1"/>
  <Setter Property="Padding" Value="2"/>
  <Setter Property="SnapsToDevicePixels" Value="true"/>
  <Setter Property="OverridesDefaultStyle" Value="true"/>
  <Setter Property="MinHeight" Value="23"/>
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate
        TargetType="{x:Type Button}">
        <Border
          x:Name="Border"
          Background="{TemplateBinding Background}"
          BorderBrush="{TemplateBinding BorderBrush}"
          BorderThickness="{TemplateBinding BorderThickness}"
          CornerRadius="2">
          <ContentPresenter
            HorizontalAlignment="Center"
            Margin="{TemplateBinding Padding}"
            VerticalAlignment="Center"
            RecognizesAccessKey="True"/>
        </Border>
        <ControlTemplate.Triggers>
          <Trigger Property="IsPressed" Value="true">
            <Setter TargetName="Border" Property="Background" Value="#808080"/>
            <Setter TargetName="Border" Property="BorderBrush" Value="#606060"/>
          </Trigger>
        </ControlTemplate.Triggers>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

希望对你有帮助

<Button
  Width="100"
  HorizontalAlignment="Center"
  VerticalAlignment="Center"
  Content="Click Me"/>

编辑

使用转换器的更好解决方案

<StackPanel HorizontalAlignment="Center"
            VerticalAlignment="Center"
            Orientation="Horizontal">
  <StackPanel.Resources>
    <wpfApplication2:MouseOverToBackgroundConverter x:Key="MouseOverToBackgroundConverter"
                                                    NormalBackground="LightGreen"
                                                    SelfMouseOverBackground="Red"
                                                    MouseOverBackground="Firebrick" />

    <Style x:Key="styleWithTrigger" TargetType="Rectangle">
      <Setter Property="Fill" Value="LightGreen" />
      <Style.Triggers>
        <Trigger Property="IsMouseOver" Value="True">
          <Setter Property="Fill" Value="Red" />
        </Trigger>
      </Style.Triggers>
    </Style>
  </StackPanel.Resources>
  <Rectangle Width="100" Height="100"
              Margin="5" Style="{StaticResource styleWithTrigger}">
    <Rectangle.Fill>
      <MultiBinding Converter="{StaticResource MouseOverToBackgroundConverter}">
        <Binding RelativeSource="{RelativeSource Self}" Path="IsMouseOver" Mode="OneWay" />
        <Binding ElementName="theOtherRect" Path="IsMouseOver" Mode="OneWay" />
      </MultiBinding>
    </Rectangle.Fill>
  </Rectangle>
  <Rectangle x:Name="theOtherRect"
              Width="100" Height="100"
              Margin="5" Style="{StaticResource styleWithTrigger}" />
</StackPanel>

转换器

public class MouseOverToBackgroundConverter : IMultiValueConverter
{
  public Brush NormalBackground { get; set; }
  public Brush SelfMouseOverBackground { get; set; }
  public Brush MouseOverBackground { get; set; }

  public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
  {
    if (values[0] is bool && values[1] is bool) {
      var selfIsMouseOver = (bool)values[0];
      var otherIsMouseOver = (bool)values[1];
      if (selfIsMouseOver) {
        return this.SelfMouseOverBackground;
      }
      return otherIsMouseOver ? this.MouseOverBackground : this.NormalBackground;
    }
    return this.NormalBackground;
  }

  public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
  {
    return targetTypes.Select(t => DependencyProperty.UnsetValue).ToArray();
  }
}

【讨论】:

  • 你的代码只有被点击后才能从#C0C0C0变成#808080对吧?但是不能再改回#C0C0C0吧?
  • @IsaacLem 他是一个例子,试试看 (kaxaml.com) 并了解有关触发器的知识 (wpftutorial.net/Triggers.html) ...
  • 好的,从链接中你可以看到绿色和红色的框对吗?当IsMouseOver 时,该框将被填充为红色。现在我想要的是,当IsMouseOver在右边的盒子里时,左边的盒子会被红色填充!
  • @IsaacLem 看看我上次的编辑,带有矩形和转换器的简单示例
猜你喜欢
  • 2015-02-04
  • 2014-04-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-08
  • 2010-10-19
  • 1970-01-01
相关资源
最近更新 更多