3

我正在尝试重新设计一些 ToggleButtons。显然我不能简单地将背景设置为新颜色,因为有一个“控制模板”提供了切换按钮的视觉行为。所以我需要做的是在 XAML 中为 ToggleButton 指定一个替换“ControlTemplate”,它提供不同的视觉行为,除了简单的背景颜色。
Q1。它是否正确?


我想从我从这里抓取的 ToggleButton 的“默认”控件模板开始,然后对其进行修改。实际上,我猜这是 Silverlight 的默认 ControlTemplate,而且我没有使用 Silverlight,我使用的是 WPF。但是... WPF 的相应文档页面不包含默认控件模板的规范。它提供了“一个”ControlTemplate,这不是我想要的。
Q2。我不确定我使用 Silverlight 的东西是否重要。可以?


在 Silverlight 示例中,有一个 vsm 的 XML 命名空间前缀应用于 VisualStateManager。显然 xml 命名空间是

  xmlns:vsm = "clr-namespace:System.Windows;assembly=System.Windows"  

...但在其他地方我读到这个 ​​XML 命名空间“不再需要”。

这一切都非常令人困惑。

在 Googlespace 中,有对我之前接触过的称为“WPF 工具包”的引用 -在 WPF V4 发布之前,我将它用于自动完成文本框。我猜想一些 WPF Toolkit 的东西被纳入 WPF for .NET v4.0,这就是我不再需要指定 WPF 工具包的原因。
第三季度。如果有人能证实这种理解,我将不胜感激。


好的,现在从 ToggleButton 的“默认”ControlTemplate 开始,我的第一步是在进行任何更改之前对其进行编译。它不编译,失败

c:\dev...\ToggleButtonStyle1.xaml(23,14): 错误 MC3074: XML 命名空间中不存在标记“VisualStateManager.VisualStateGroups” http://schemas.microsoft.com/winfx/2006/xaml/演示文稿'。第 23 行位置 14。

够清楚。然后我查看了在 XAML 中指定 VisualStateManager 的文档。令人困惑的是,它指定了两个 xml 命名空间,其中一个是我实际使用的。

在此处输入图像描述

Q4嗯,我应该使用哪个?其中之一,我确实使用过,但它没有用。该文档完全不清楚指定两个 XML 名称空间的含义。(砍掉他们的头!)

我在项目文件中有对 PresentationFramework.dll 的引用:

  <ItemGroup>
     ....
    <Reference Include="PresentationFramework" />
  </ItemGroup>

我在这里没有使用 Visual Studio;我正在使用文本编辑器。我想了解它是如何工作的,而不是要按什么按钮。

感谢您提供的任何帮助。


只是一个侧面评论 - 这一切似乎非常非常复杂。我想做的就是在打开时更改 ToggleButton 的颜色。真的不应该这么复杂。

4

2 回答 2

5

您不需要为 VSM 指定命名空间(http://schemas.microsoft.com/winfx/2006/xaml/presentation命名空间是默认的 WPF 命名空间,在大多数标准中声明为 xmlns="..." .xaml's) -- 但是,您只能在视觉层次结构的某些部分使用它。

例如,当我在标准 UserControl 中使用 VSM 时,它看起来像这样:

<UserControl x:Class="Whatever"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <Grid x:Name="LayoutRoot">
    <VisualStateManager.VisualStateGroups>
      <VisualStateGroup x:Name="CommonStates">
        <VisualState x:Name="Disabled">
          <!-- Storyboards go here -->
        </VisualState>
      </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>
  </Grid>
</UserControl>

将 VSM xaml 放置在此级别将使您的故事板能够引用网格中包含的任何元素。这在您正在使用的 ControlTemplate 中的工作方式相同。不过要注意的一件事是,在您自己的UserControls 中,您可以随意命名视觉状态(因为您最终将在代码中调用以切换到该视觉状态),使用内置控件,您的视觉状态必须准确地命名为控件所期望的。

于 2011-09-06T19:37:38.707 回答
0

回答我自己的问题....
Q1
Q2否 - 没关系。模板“大约”相同。
Q3不确定
Q4我不知道。

这里的关键是我需要指定 TargetFramework = 4.0。我一直在针对 v3.5 进行编译,并且我猜想 VSM 首先在 v4.0 中可用,所以这就是“在命名空间 xxxxx 中找不到”错误的原因。

我不需要在 XAML 文件中指定 XMLNS。

退后一步 - 更大问题的答案 - 如何获得一个在按下时改变颜色的 ToggleButton……我尝试摆弄内置的 ControlTemplate,但它太复杂了,我无法理解。Press 和 Checked 等发生的动画 - 我永远无法弄清楚如何让它做我想做的事情。

我将模板剥离为更多备用的东西,没有所有的渐变和动画,然后我添加了一些动画和触发器,以使其完成我想要它做的事情。
视觉效果是这样的。在:

在此处输入图像描述

离开:

在此处输入图像描述


我使用的 XAML:

<ResourceDictionary xmlns     = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x   = "http://schemas.microsoft.com/winfx/2006/xaml">
  <Style x:Key      = "ToggleButtonStyle3"
         TargetType = "ToggleButton">

<!-- This is a style (template?) for a toggle button. I wanted it to
     change to a contrasty color when depressed. This took me a
     loooooong time and much trial and error to figure out. The visual
     effect is somewhat like the buttons in the compile output log in
     Visual Studio, in which you can toggle the display of errors and
     warnings.
-->
    <Setter Property="Background" Value="#FFF7F0D2"/>
    <Setter Property="Foreground" Value="#FF000000"/>
    <Setter Property="Padding" Value="3"/>
    <Setter Property="BorderThickness" Value="1"/>
    <Setter Property="BorderBrush">
      <Setter.Value>
        <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
          <GradientStop Color="#FFC4BC64" Offset="0"/>
          <GradientStop Color="#FFADA658" Offset="0.375"/>
          <GradientStop Color="#FFA19A52" Offset="0.375"/>
          <GradientStop Color="#FF847E43" Offset="1"/>
        </LinearGradientBrush>
      </Setter.Value>
    </Setter>
    <Setter Property="Template">
      <Setter.Value>
        <ControlTemplate TargetType="ToggleButton">
          <Grid x:Name="ButtonGrid">
            <VisualStateManager.VisualStateGroups>
              <VisualStateGroup x:Name="CommonStates">
                <VisualState x:Name="Normal"/>
                <VisualState x:Name="MouseOver">
                  <Storyboard>
                    <DoubleAnimation Duration="0" Storyboard.TargetName="InnerRectangle" Storyboard.TargetProperty="Opacity" To="0.3"/>
                  </Storyboard>
                </VisualState>
                <VisualState x:Name="Pressed">
                  <Storyboard>
                    <ColorAnimation Duration="00:00:00"
                                    Storyboard.TargetName="InnerRectangle"
                                    Storyboard.TargetProperty="(Rectangle.Fill).(SolidColorBrush.Color)"
                                    To="#FFF5BF0F"/>
                  </Storyboard>
                </VisualState>
                <VisualState x:Name="Disabled">
                  <Storyboard>
                    <DoubleAnimation Duration="0" Storyboard.TargetName="DisabledVisualElement" Storyboard.TargetProperty="Opacity" To=".55"/>
                  </Storyboard>
                </VisualState>
              </VisualStateGroup>
              <VisualStateGroup x:Name="CheckStates">
                <VisualState x:Name="Checked">
                  <Storyboard>
                    <ColorAnimation Duration="00:00:00"
                                    Storyboard.TargetName="InnerRectangle"
                                    Storyboard.TargetProperty="(Rectangle.Fill).(SolidColorBrush.Color)"
                                    To="#FFF5D018"/>
                  </Storyboard>
                </VisualState>
                <VisualState x:Name="Unchecked"/>
              </VisualStateGroup>
              <VisualStateGroup x:Name="FocusStates">
                <VisualState x:Name="Focused">
                  <Storyboard>
                    <DoubleAnimation Duration="0" Storyboard.TargetName="FocusVisualElement" Storyboard.TargetProperty="Opacity" To="1"/>
                  </Storyboard>
                </VisualState>
                <VisualState x:Name="Unfocused" />
              </VisualStateGroup>
            </VisualStateManager.VisualStateGroups>

            <Border x:Name          ="ButtonBorder"
                    CornerRadius    ="1"
                    Background      ="{TemplateBinding Background}"
                    BorderThickness ="{TemplateBinding BorderThickness}"
                    BorderBrush     ="{TemplateBinding BorderBrush}">
              <Border x:Name="InnerButtonBorder"
                      CornerRadius="1"
                      BorderThickness="2"
                      Background="#FFFAEB16">
                <Rectangle x:Name="InnerRectangle" Opacity="1" Fill="#F7F0D2" />
              </Border>
            </Border>

            <ContentPresenter
                x:Name="contentPresenter"
                Content="{TemplateBinding Content}"
                ContentTemplate="{TemplateBinding ContentTemplate}"
                VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                TextBlock.Foreground="{TemplateBinding Foreground}"
                Margin="{TemplateBinding Padding}"/>
            <Rectangle x:Name="DisabledVisualElement" RadiusX="3" RadiusY="3" Fill="#FFFFFFFF" Opacity="0" IsHitTestVisible="false" />
            <Rectangle x:Name="FocusVisualElement" RadiusX="2" RadiusY="2" Margin="1" Stroke="#FFD1C44D" StrokeThickness="1" Opacity="0" IsHitTestVisible="false" />
          </Grid>
          <ControlTemplate.Triggers>

            <Trigger Property="ToggleButton.IsChecked" Value="True">
              <!-- This setter hides the desired element when the ToggleButton's initial state is checked -->
              <Setter TargetName="ButtonBorder" Property="Background" Value="#FFF5D018"/>
              <Setter TargetName="contentPresenter" Property="TextBlock.Foreground" Value="#FF000000"/>
            </Trigger>
            <Trigger Property="ToggleButton.IsChecked" Value="False">
              <Setter TargetName="contentPresenter" Property="TextBlock.Foreground" Value="#78999999"/>
            </Trigger>
          </ControlTemplate.Triggers>
        </ControlTemplate>
      </Setter.Value>
    </Setter>
  </Style>
</ResourceDictionary>

我把它放到一个单独的文件中,称之为 ToggleButtonStyle3.xaml。然后我像这样使用它:

<Window.Resources>
  <ResourceDictionary>
    <Style ....
    </Style>
    <ResourceDictionary.MergedDictionaries>
      <ResourceDictionary Source="Resources/ToggleButtonStyle3.xaml" />
    </ResourceDictionary.MergedDictionaries>
  </ResourceDictionary>
</Window.Resources>
....

         <ToggleButton Name       ="btnShowAlerts"
                      IsChecked  ="{Binding Path=ShowAlerts, Mode=TwoWay}"
                      Style      ="{StaticResource ToggleButtonStyle3}"
                      Content    ="alerts"
                      FontSize   ="9"
                      Padding    ="8,2"
                      Margin     ="0"
                      ClickMode  ="Press"
                      />

我不知道这是否是最好的做事方式。我知道它不符合桌面的“主题”。我知道这可能很基本。我只知道我花了很长时间才弄清楚如何获得一个改变颜色的 ToggleButton。

于 2011-09-07T01:48:04.997 回答