XAML 在不改变颜色的情况下改变背景不透明度

mba*_*tas 7 c# wpf xaml

在我的C# / WPF / .NET 4.5应用程序中,我想实现一个Trigger在不改变控件颜色的情况下切换控件的背景不透明度。

通常要设置控件的背景画笔,我会使用以下内容Setter

<Setter TargetName="TargetControl" Property="Background">
<Setter.Value>
  <SolidColorBrush Color="Red" Opacity="0.2"/>
</Setter.Value>
Run Code Online (Sandbox Code Playgroud)

现在我处于一种情况,我只需要改变不透明度而不是颜色。在这种情况下,我的 setter 会是什么样子,我不在乎背景是什么颜色,但我想在更改不透明度的同时保留颜色?

更多细节:

这样做的原因是我正在研究ItemsControl背景颜色根据项目的变化而变化的地方AlternationIndex

<ItemsControl ItemsSource="{Binding SomeCollection}" AlternationCount="6">
  <ItemsControl.ItemTemplate>
    <DataTemplate>
      <Grid x:Name="GridWithin">
      <!-- ... -->
      </Grid>
      <DataTemplate.Triggers>
        <!-- Aternating colors for each row -->
        <Trigger Property="ItemsControl.AlternationIndex" Value="0">
          <Setter TargetName="GridWithin" Property="Background">
            <Setter.Value>
              <SolidColorBrush Color="Red" Opacity="0.2"/>
            </Setter.Value>
          </Setter>
        </Trigger>
        <Trigger Property="ItemsControl.AlternationIndex" Value="1">
          <Setter TargetName="AllGesturesDataTemplateGrid" Property="Background">
            <Setter.Value>
              <SolidColorBrush Color="Green" Opacity="0.2"/>
            </Setter.Value>
          </Setter>
        </Trigger>
        <!-- ... -->
        <!-- Highlight when a hit is registered -->
        <DataTrigger>
          <DataTrigger.Conditions>
            <Condition Binding="{Binding IsHit}" Value="True" />
          </MultiDataTrigger.Conditions>
          <!-- The culprit -->
          <Setter TargetName="GridWithin" Property="Background">
            <Setter.Value>
              <SolidColorBrush Opacity="0.7"/>
            </Setter.Value>
          </Setter>
          <!-- /culprit -->
        </DataTrigger>
      </DataTemplate.Triggers>
    </DataTemplate>
  </ItemsControl.ItemTemplate>
</ItemsControl>
Run Code Online (Sandbox Code Playgroud)

She*_*dan 7

我花了一点时间才想到这样做的最佳方法……结果证明这比我最初想象的要棘手。尽管如此,这是可能的,但它确实涉及相当多的代码。为了能够定位对象的实际Opacity属性Background Brush,您需要使用StoryBoard... 这就是此代码示例如此冗长的原因。

因为我们需要在 中使用一个Storyboard对象DataTrigger,这意味着我们必须使用 ,DataTrigger.EnterActions因为 aStoryboard不能在普通DataTrigger.Setters集合中使用。这意味着我们还必须使用DataTrigger.ExitActions来提供另一个StoryboardOpacity属性设置回其原始值的方法。尝试这个:

<Grid Name="YourGrid">
    <Grid.Background>
        <SolidColorBrush Color="Green" Opacity="0.2" />
    </Grid.Background>
    <Grid.Style>
        <Style TargetType="{x:Type Grid}">
            <Style.Triggers>
                <DataTrigger Binding="{Binding IsMouseOver, ElementName=YourGrid}" 
                    Value="True">
                    <DataTrigger.EnterActions>
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimationUsingKeyFrames 
Storyboard.TargetProperty="Background.(SolidColorBrush.Opacity)">
                                    <LinearDoubleKeyFrame Value="0.7" KeyTime="0:0:0"/>
                                </DoubleAnimationUsingKeyFrames>
                            </Storyboard>
                        </BeginStoryboard>
                    </DataTrigger.EnterActions>
                    <DataTrigger.ExitActions>
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimationUsingKeyFrames 
Storyboard.TargetProperty="Background.(SolidColorBrush.Opacity)">
                                    <LinearDoubleKeyFrame Value="0.2" KeyTime="0:0:0"/>
                                </DoubleAnimationUsingKeyFrames>
                            </Storyboard>
                        </BeginStoryboard>
                    </DataTrigger.ExitActions>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </Grid.Style>
</Grid>
Run Code Online (Sandbox Code Playgroud)

尽管实现此方法需要大量代码,但它确实可以满足您的需求。但是,有一种更简单的方法可以获得相同的整体效果,但代码略少。您可以简单地Rectangle在每个Grid单元格或分区的背面添加一个,并在其上设置颜色和不透明度。使用这种方法,您可以简单地直接设置Rectangle.Opacity值,尽管您会使用额外的控件……选择权在您手中。