如何根据父控件的不透明度控制后代控件的不透明度?

时间:2014-02-26 07:31:38

标签: wpf xaml opacity

我创建了一个用户控件,网格中有网格和几个控件。我已将Opacity设置为我父网格的.1,并且我想将后代控件的不透明度设置为1.可以在XAML树架构中执行吗? 这是我的xaml代码:

<Grid Name="busyIndicatorGrid" Visibility="Visible" Opacity=".2"
      Background="DarkBlue" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
    <StackPanel Orientation="Vertical" Opacity="1" 
                Background="Transparent" HorizontalAlignment="Center" VerticalAlignment="Center">
        <ProgressBar Name="progressBar" Foreground="White" 
                     IsIndeterminate="True" MinWidth="100" Height="25" VerticalAlignment="Center"/>
        <TextBlock Name="txtProgressText" 
                   FontSize="40" 
                   Margin="0,5,0,0" 
                   Text="Please wait while application is being initialized."
                   TextAlignment="Left" TextWrapping="Wrap" />
    </StackPanel>
</Grid>

2 个答案:

答案 0 :(得分:0)

不透明度是一个将在子树下传播的属性。

如果父不透明度为0.5且子透明度为0.2,则父级将以50%绘制,子级将使用父级50%的20%绘制...有点像那样只是为了更好地理解...我希望你得到我:)。

试试这个,你会看到:

<Grid Name="busyIndicatorGrid" Visibility="Visible" Opacity=".2">
     <StackPanel Orientation="Vertical" Opacity="1" >
     ...

<Grid Name="busyIndicatorGrid" Visibility="Visible" Opacity=".2">
     <StackPanel Orientation="Vertical" Opacity="0.5">
    ...

这两个将以不同的方式绘制,这意味着孩子不会从其父级获取不透明度值,而是计算自己的值。

如果你想控制内部子项的绘制方式,我建议你创建一个附加属性,在VisualTree中继承它的内容,当设置为true时,它会改变其“underneathly”相关元素的不透明度1或以前的旧值。

以下是一个例子:

    public static bool GetChangeOpacity(DependencyObject obj)
    {
        return (bool)obj.GetValue(ChangeOpacityProperty);
    }

    public static void SetChangeOpacity(DependencyObject obj, bool value)
    {
        obj.SetValue(ChangeOpacityProperty, value);
    }

    // Using a DependencyProperty as the backing store for ChangeOpacity.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty ChangeOpacityProperty =
        DependencyProperty.RegisterAttached("ChangeOpacity", typeof(bool), typeof(YourClass), new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.Inherits, PropertyChangedCallback));

    private static void PropertyChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs args)
    {
        FrameworkElement fe = dependencyObject as FrameworkElement;
        if (fe != null && (bool)args.NewValue)
        {
            fe.Tag = fe.Opacity;
            fe.Opacity = 1;
        }
        else if(fe != null && fe.Tag != null)
        {
            fe.Opacity = (double)fe.Tag;
        }
    }

答案 1 :(得分:0)

谢谢你们提出宝贵的建议。但我已经找到了通过使用画笔作为父网格控件解决我的问题的方法。

<Grid Name="busyIndicatorGrid" Visibility="Visible" Opacity=".2"
  HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
    <Grid.Background>
        <SolidColorBrush Color="DarkBlue" Opacity="0.2"/>
    </Grid.Background>
<StackPanel Orientation="Vertical"
            Background="Transparent" HorizontalAlignment="Center" VerticalAlignment="Center">
    <ProgressBar Name="progressBar" Foreground="White" 
                 IsIndeterminate="True" MinWidth="100" Height="25" VerticalAlignment="Center"/>
    <TextBlock Name="txtProgressText" 
               FontSize="40" 
               Margin="0,5,0,0" 
               Text="Please wait while application is being initialized."
               TextAlignment="Left" TextWrapping="Wrap" />
</StackPanel>

通过这样做,它将使用我在background属性中定义的不透明度绘制父网格,它对内部控件没有任何影响。所有控件都将照常绘制,而不会在父网格上设置任何不透明覆盖效果。