简体   繁体   English

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

[英]XAML to change background opacity without changing color

In my C# / WPF / .NET 4.5 app I would like to implement a Trigger that toggles the background opacity of a control without changing its color.在我的C# / WPF / .NET 4.5应用程序中,我想实现一个Trigger来切换控件的背景不透明度而不改变其颜色。

Normally to set the background brush of a control, I would use the following Setter :通常要设置控件的背景画笔,我会使用以下Setter

<Setter TargetName="TargetControl" Property="Background">
<Setter.Value>
  <SolidColorBrush Color="Red" Opacity="0.2"/>
</Setter.Value>

Now I am in a situation where I have to change the opacity only and not the color.现在我处于一种情况,我只需要改变不透明度而不是颜色。 What would my setter look like in this case, where I don't care what color the background is but I want to preserve the color while changing the opacity?在这种情况下,我的 setter 会是什么样子,我不在乎背景是什么颜色,但我想在更改不透明度的同时保留颜色?

More details:更多细节:

The reason for this is that I am working on an ItemsControl where the background color changes depending on the item's AlternationIndex :这样做的原因是我正在处理一个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>

It took me a little while to think of the best way to do this... it turns out that it was trickier than I had first thought.我花了一点时间才想出最好的方法来做到这一点……结果证明这比我最初想象的要棘手。 All the same, it is possible, but it does involve quite a lot of code.尽管如此,这是可能的,但它确实涉及相当多的代码。 In order to be able to target the actual Opacity property of the Background Brush object, you'll need to use a StoryBoard ... that's why this code example is so verbose.为了能够定位Background Brush对象的实际Opacity属性,您需要使用StoryBoard ......这就是为什么这个代码示例如此冗长。

Because we need to use a Storyboard object in the DataTrigger , that means that we must use the DataTrigger.EnterActions as a Storyboard cannot be used in the normal DataTrigger.Setters collection.因为我们需要在DataTrigger使用Storyboard对象,这意味着我们必须使用DataTrigger.EnterActions作为Storyboard不能在正常的DataTrigger.Setters集合中使用。 This follows that we must also use the DataTrigger.ExitActions to provide another Storyboard that sets the Opacity property back to its original value.因此,我们还必须使用DataTrigger.ExitActions提供另一个Storyboard ,将Opacity属性设置回其原始值。 Try this:尝试这个:

<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>

Despite the amount of code required to implement this method, it does do exactly what you were after.尽管实现此方法需要大量代码,但它确实可以满足您的需求。 However, there is a simpler way to get the same overall effect, but with slightly less code.但是,有一种更简单的方法可以获得相同的整体效果,但代码略少。 You could simply add a Rectangle into the back of each Grid cell, or division and set the colours and opacity on that instead.可以简单地在每个Grid单元格的背面添加一个Rectangle ,或者在其上设置颜色和不透明度。 Using this method, you could simply set the Rectangle.Opacity value directly, although you would be using extra controls... the choice is yours.使用此方法,您可以简单地直接设置Rectangle.Opacity值,尽管您将使用额外的控件......选择权在您手中。

This answer is almost identical to @Sheridans, but it saves a few lines of XAML (and there are always too many as it is...)这个答案几乎与@Sheridans 相同,但它节省了几行 XAML(而且总是太多……)

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 Storyboard.TargetProperty="Background.(SolidColorBrush.Opacity)">
                                <DoubleAnimation To="0.7" Duration="0" />
                            </Storyboard>
                        </BeginStoryboard>
                    </DataTrigger.EnterActions>
                    <DataTrigger.ExitActions>
                        <BeginStoryboard>
                            <Storyboard Storyboard.TargetProperty="Background.(SolidColorBrush.Opacity)">
                                <DoubleAnimation To="0.2" Duration="0" />
                            </Storyboard>
                        </BeginStoryboard>
                    </DataTrigger.ExitActions>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </Grid.Style>
</Grid>

"Grid" has its own "Opacity" property as well as a "Background" property. “Grid”有自己的“Opacity”属性和“Background”属性。 Perhaps use your trigger to change that opacity and leave the background colour alone?也许使用您的触发器来更改不透明度并单独保留背景颜色?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM