Scrollviewer边缘模糊效果,opacitymask无法正常工作

时间:2009-12-14 15:53:28

标签: wpf scrollviewer

我想在不使用滚动条的情况下为触摸屏应用程序创建自定义scrollviewer控件。为了让用户知道他们可以滚动内容,我使用opacitymask以线性渐变淡化滚动查看器的底部和顶部。这一切都很好,除了滚动查看器之外的opacitymask应用于文本块的问题!

我的意思是,我希望将淡化效果应用于scrollviewer的顶部1%和底部1%,然后滚动查看器的中间部分将可见。然而,问题是,即使我在文本块上设置了OpacityMask =“{x:Null}”,滚动查看器中的控件也会发生这种效果。

我已尝试将opacitymask应用于scrollviewer的外部,但同样的问题也会发生。 Opacitymask属性是否也适用于孩子?是否有更好的方法来实现这种褪色效果?

以下是我正在使用的代码:

<Grid Width="200" Height="130">
    <ScrollViewer BorderThickness="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Padding="2"
                           HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Hidden" >
        <ScrollViewer.OpacityMask>
            <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
                <GradientStop Color="Transparent" Offset="0" />
                <GradientStop Color="Black" Offset="0.1" />
                <GradientStop Color="Black" Offset="0.9" />
                <GradientStop Color="Transparent" Offset="1" />
            </LinearGradientBrush>
        </ScrollViewer.OpacityMask>
        <TextBlock Margin="0,10" Style="{StaticResource textSmall}" TextWrapping="Wrap">
        Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum
        </TextBlock>
    </ScrollViewer>
</Grid>

5 个答案:

答案 0 :(得分:6)

我知道这是一个较老的问题,但我遇到了这个问题,因为我试图做类似的事情;所以我想我会为下一个人发布我的解决方案。对我的解决方案的任何反馈都表示赞赏。

在我们的应用程序中,我们的大多数ScrollViewer控件都位于非滚动纹理之上,因此我们希望可滚动内容在ScrollViewer边缘淡入到该背景中,但只有在该方向上有更多内容时才会这样。此外,我们至少有一个2轴可滚动区域,用户可以在每个方向上平移。它也必须在那种情况下工作。我们的应用程序也没有真正的滚动条,但我已经把它从我在这里提出的解决方案中删除了(它不会影响解决方案)。

此解决方案的特点:

  1. 如果ScrollViewer的那一侧内容当前不可见,则会淡化ScrollViewer中内容的边缘。

  2. 在靠近内容边缘滚动时,减小淡入淡出效果的强度。

  3. 可以控制褪色边缘的外观。具体来说,你可以控制:

    1. 褪色边缘的厚度
    2. 内容在最外边缘的不透明程度(或淡化程度“强烈”)
    3. 在边缘附近滚动时淡出效果消失的速度
  4. 基本思想是控制ScrollViewer模板中可滚动内容的不透明蒙版。不透明蒙版包含透明外边框和内部不透明边框,其中应用了BlurEffect以获得边缘处的渐变效果。然后,在您滚动时控制内边框的边距,以控制淡化沿特定边缘出现的“深度”。

    此解决方案是ScrollViewer的子类,需要您指定对ScrollViewer模板的更改。 ScrollContentPresenter需要包装在名为“PART_ScrollContentPresenterContainer”的边框内。

    FadingScrollViewer类

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Media;
    using System.Windows.Media.Effects;
    
    namespace ScrollViewerTest
    {
      public class FadingScrollViewer : ScrollViewer
      {
        private const string PART_SCROLL_PRESENTER_CONTAINER_NAME = "PART_ScrollContentPresenterContainer";
    
        public double FadedEdgeThickness { get; set; }
        public double FadedEdgeFalloffSpeed { get; set; }
        public double FadedEdgeOpacity { get; set; }
    
        private BlurEffect InnerFadedBorderEffect { get; set; }
        private Border InnerFadedBorder { get; set; }
        private Border OuterFadedBorder { get; set; }
    
    
    
        public FadingScrollViewer()
        {
          this.FadedEdgeThickness = 20;
          this.FadedEdgeFalloffSpeed = 4.0;
          this.FadedEdgeOpacity = 0.0;
    
          this.ScrollChanged += FadingScrollViewer_ScrollChanged;
          this.SizeChanged += FadingScrollViewer_SizeChanged;
        }
    
    
    
        private void FadingScrollViewer_ScrollChanged(object sender, ScrollChangedEventArgs e)
        {
          if (this.InnerFadedBorder == null)
            return;
    
          var topOffset = CalculateNewMarginBasedOnOffsetFromEdge(this.VerticalOffset); ;
          var bottomOffset = CalculateNewMarginBasedOnOffsetFromEdge(this.ScrollableHeight - this.VerticalOffset);
          var leftOffset = CalculateNewMarginBasedOnOffsetFromEdge(this.HorizontalOffset);
          var rightOffset = CalculateNewMarginBasedOnOffsetFromEdge(this.ScrollableWidth - this.HorizontalOffset);
    
          this.InnerFadedBorder.Margin = new Thickness(leftOffset, topOffset, rightOffset, bottomOffset);
        }
    
    
    
        private double CalculateNewMarginBasedOnOffsetFromEdge(double edgeOffset)
        {
          var innerFadedBorderBaseMarginThickness = this.FadedEdgeThickness / 2.0;
          var calculatedOffset = (innerFadedBorderBaseMarginThickness) - (1.5 * (this.FadedEdgeThickness - (edgeOffset / this.FadedEdgeFalloffSpeed)));
    
          return Math.Min(innerFadedBorderBaseMarginThickness, calculatedOffset);
        }
    
    
    
        private void FadingScrollViewer_SizeChanged(object sender, SizeChangedEventArgs e)
        {
          if (this.OuterFadedBorder == null || this.InnerFadedBorder == null || this.InnerFadedBorderEffect == null)
            return;
    
          this.OuterFadedBorder.Width = e.NewSize.Width;
          this.OuterFadedBorder.Height = e.NewSize.Height;
    
          double innerFadedBorderBaseMarginThickness = this.FadedEdgeThickness / 2.0;
          this.InnerFadedBorder.Margin = new Thickness(innerFadedBorderBaseMarginThickness);
          this.InnerFadedBorderEffect.Radius = this.FadedEdgeThickness;
        }
    
    
    
        public override void OnApplyTemplate()
        {
          base.OnApplyTemplate();
    
          BuildInnerFadedBorderEffectForOpacityMask();
          BuildInnerFadedBorderForOpacityMask();
          BuildOuterFadedBorderForOpacityMask();
          SetOpacityMaskOfScrollContainer();
        }
    
    
    
        private void BuildInnerFadedBorderEffectForOpacityMask()
        {
          this.InnerFadedBorderEffect = new BlurEffect()
            {
              RenderingBias = RenderingBias.Performance,
            };
        }
    
    
    
        private void BuildInnerFadedBorderForOpacityMask()
        {
          this.InnerFadedBorder = new Border()
            {
              Background = Brushes.Black,
              HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch,
              VerticalAlignment = System.Windows.VerticalAlignment.Stretch,
              Effect = this.InnerFadedBorderEffect,
            };
        }
    
    
    
        private void BuildOuterFadedBorderForOpacityMask()
        {
          byte fadedEdgeByteOpacity = (byte)(this.FadedEdgeOpacity * 255);
    
          this.OuterFadedBorder = new Border()
            {
              Background = new SolidColorBrush(Color.FromArgb(fadedEdgeByteOpacity, 0, 0, 0)),
              ClipToBounds = true,
              Child = this.InnerFadedBorder,
            };
        }
    
    
    
        private void SetOpacityMaskOfScrollContainer()
        {
          var opacityMaskBrush = new VisualBrush()
            {
              Visual = this.OuterFadedBorder
            };
    
          var scrollContentPresentationContainer = this.Template.FindName(PART_SCROLL_PRESENTER_CONTAINER_NAME, this) as UIElement;
    
          if (scrollContentPresentationContainer == null)
            return;
    
          scrollContentPresentationContainer.OpacityMask = opacityMaskBrush;
        }
      }
    }
    

    这是使用控件的XAML,对所需的默认ScrollViewer模板进行了最小的更改(它是ScrollContentPresenter周围的边框)。

    <local:FadingScrollViewer HorizontalScrollBarVisibility="Visible" VerticalScrollBarVisibility="Visible" Margin="10" FadedEdgeThickness="20" FadedEdgeOpacity="0" FadedEdgeFalloffSpeed="4">
      <local:FadingScrollViewer.Template>
        <ControlTemplate TargetType="{x:Type ScrollViewer}">
          <Grid x:Name="Grid" Background="{TemplateBinding Background}">
            <Grid.ColumnDefinitions>
              <ColumnDefinition Width="*"/>
              <ColumnDefinition Width="Auto"/>
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
              <RowDefinition Height="*"/>
              <RowDefinition Height="Auto"/>
            </Grid.RowDefinitions>
    
            <Border x:Name="PART_ScrollContentPresenterContainer">
              <ScrollContentPresenter x:Name="PART_ScrollContentPresenter" CanContentScroll="{TemplateBinding CanContentScroll}" CanHorizontallyScroll="False" CanVerticallyScroll="False" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" Grid.Column="0" Margin="{TemplateBinding Padding}" Grid.Row="0"/>
            </Border>
    
            <ScrollBar x:Name="PART_VerticalScrollBar" AutomationProperties.AutomationId="VerticalScrollBar" Cursor="Arrow" Grid.Column="1" Maximum="{TemplateBinding ScrollableHeight}" Minimum="0" Grid.Row="0" Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}" Value="{Binding VerticalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}" ViewportSize="{TemplateBinding ViewportHeight}"/>
            <ScrollBar x:Name="PART_HorizontalScrollBar" AutomationProperties.AutomationId="HorizontalScrollBar" Cursor="Arrow" Grid.Column="0" Maximum="{TemplateBinding ScrollableWidth}" Minimum="0" Orientation="Horizontal" Grid.Row="1" Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}" Value="{Binding HorizontalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}" ViewportSize="{TemplateBinding ViewportWidth}"/>
          </Grid>
        </ControlTemplate>
      </local:FadingScrollViewer.Template>
    
    
      <!-- Your content here -->
    
    </local:FadingScrollViewer>
    

    请注意FadedScrollViewer上的这些附加属性:FadedEdgeThickness,FadedEdgeOpacity和FadedEdgeFalloffSpeed

    • FadedEdgeThickness:您希望淡入淡出的厚度(以像素为单位)
    • FadedEdgeOpacity:你想要淡化的最外边缘是多么不透明。 0 =边缘处完全透明,1 =边缘处不会褪色
    • FadedEdgeFalloffSpeed:控制褪色边缘在接近它时消失的速度。值越高,淡出越慢。

答案 1 :(得分:3)

我改变了Grandpappy的代码,无需使用自定义控件。 像这样,只需向它们添加附加属性,就可以将所有ScrollViewers“升级”为淡入滚动查看器。 您还需要为scrollviewer指定一种样式,无论如何我都要这样做。它必须定义名称PART_ScrollContentPresenterContainer。您无需修改​​即可使用Grandpappys Style。

该类的代码(称为ScrollViewerExtensions)是:

/// <summary>
/// Attached property that makes the scrollbar fade on it's edges
/// 
/// derived class at from http://stackoverflow.com/questions/1901709/scrollviewer-edge-blur-effect-opacitymask-not-working-properly
/// </summary>
public class ScrollViewerExtensions : DependencyObject
{
    /// <summary>
    /// MAIN property: this activates the whole fading effect
    /// </summary>
    public static readonly DependencyProperty FadedEdgeThicknessProperty =
        DependencyProperty.RegisterAttached("FadedEdgeThickness", typeof(double), typeof(ScrollViewerExtensions), new PropertyMetadata(20.0d, OnFadedEdgeThicknessChanged));

    public static void SetFadedEdgeThickness(ScrollViewer s, double value)
    {
        s.SetValue(FadedEdgeThicknessProperty, value);
    }

    public static double GetFadedEdgeThickness(ScrollViewer s, double value)
    {
        return (double)s.GetValue(FadedEdgeThicknessProperty);
    }

    /// <summary>
    /// optional property. changes how fast the fade appears/diappears when scrolling near an edge
    /// </summary>
    public static readonly DependencyProperty FadedEdgeFalloffSpeedProperty =
        DependencyProperty.RegisterAttached("FadedEdgeFalloffSpeed", typeof(double), typeof(ScrollViewerExtensions), new PropertyMetadata(4.0d, OnFadedEdgeFalloffSpeedChanged));

    public static void SetFadedEdgeFalloffSpeed(ScrollViewer s, double value)
    {
        s.SetValue(FadedEdgeFalloffSpeedProperty, value);
    }

    public static double GetFadedEdgeFalloffSpeed(ScrollViewer s, double value)
    {
        return (double)s.GetValue(FadedEdgeFalloffSpeedProperty);
    }

    /// <summary>
    /// optional property. changes how opaque the outermost edge should be
    /// </summary>
    public static readonly DependencyProperty FadedEdgeOpacityProperty =
        DependencyProperty.RegisterAttached("FadedEdgeOpacity", typeof(double), typeof(ScrollViewerExtensions), new PropertyMetadata(0.0d, OnFadedEdgeOpacityChanged));

    public static void SetFadedEdgeOpacity(ScrollViewer s, double value)
    {
        s.SetValue(FadedEdgeOpacityProperty, value);
    }

    public static double GetFadedEdgeOpacity(ScrollViewer s, double value)
    {
        return (double)s.GetValue(FadedEdgeOpacityProperty);
    }




    private const string PART_SCROLL_PRESENTER_CONTAINER_NAME = "PART_ScrollContentPresenterContainer";

    private static Dictionary<ScrollViewer, FadeSettings> Settings = new Dictionary<ScrollViewer, FadeSettings>();



    /// <summary>
    /// this is kindof the constructor for the properties. If you don't specify this, nothing will fade!
    /// </summary>
    /// <param name="d"></param>
    /// <param name="e"></param>
    public static void OnFadedEdgeThicknessChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var scrollViewer = d as ScrollViewer;

        if (scrollViewer == null)
            return;

        double edgeThickness = (double)e.NewValue;

        scrollViewer.ScrollChanged += FadingScrollViewer_ScrollChanged;
        scrollViewer.SizeChanged += FadingScrollViewer_SizeChanged;

        if (!Settings.ContainsKey(scrollViewer))
            Settings.Add(scrollViewer, new FadeSettings());

        Settings[scrollViewer].FadedEdgeThickness = edgeThickness;
    }


    public static void OnFadedEdgeFalloffSpeedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var scrollViewer = d as ScrollViewer;

        if (scrollViewer == null)
            return;

        double edgeFalloffSpeed = (double)e.NewValue;

        if (!Settings.ContainsKey(scrollViewer))
            Settings.Add(scrollViewer, new FadeSettings());

        Settings[scrollViewer].FadedEdgeFalloffSpeed = edgeFalloffSpeed;
    }


    public static void OnFadedEdgeOpacityChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var scrollViewer = d as ScrollViewer;

        if (scrollViewer == null)
            return;

        double edgeOpacity = (double)e.NewValue;

        if (!Settings.ContainsKey(scrollViewer))
            Settings.Add(scrollViewer, new FadeSettings());

        Settings[scrollViewer].FadedEdgeOpacity = edgeOpacity;
    }


    private static void FadingScrollViewer_ScrollChanged(object sender, ScrollChangedEventArgs e)
    {
        ScrollViewer scrollViewer = sender as ScrollViewer;
        FadeSettings settings = Settings[scrollViewer];

        if (settings.InnerFadedBorder == null)
            return;

        var topOffset = CalculateNewMarginBasedOnOffsetFromEdge(scrollViewer, scrollViewer.VerticalOffset); ;
        var bottomOffset = CalculateNewMarginBasedOnOffsetFromEdge(scrollViewer, scrollViewer.ScrollableHeight - scrollViewer.VerticalOffset);
        var leftOffset = CalculateNewMarginBasedOnOffsetFromEdge(scrollViewer, scrollViewer.HorizontalOffset);
        var rightOffset = CalculateNewMarginBasedOnOffsetFromEdge(scrollViewer, scrollViewer.ScrollableWidth - scrollViewer.HorizontalOffset);

        settings.InnerFadedBorder.Margin = new Thickness(leftOffset, topOffset, rightOffset, bottomOffset);
    }

    private static void FadingScrollViewer_SizeChanged(object sender, SizeChangedEventArgs e)
    {
        ScrollViewer scrollViewer = sender as ScrollViewer;
        FadeSettings settings = Settings[scrollViewer];

        if (!settings.Initialized) // abuse the SizeChanged event to call the OnApplyTemplate method. We can't override it, so we need something, that fires after it would normally be called. see http://msdn.microsoft.com/en-us/library/dd351483%28v=vs.95%29.aspx
        {
            OnApplyTemplate(scrollViewer);
            settings.Initialized = true;
        }

        if (settings.OuterFadedBorder == null || settings.InnerFadedBorder == null || settings.InnerFadedBorderEffect == null)
            return;

        settings.OuterFadedBorder.Width = e.NewSize.Width;
        settings.OuterFadedBorder.Height = e.NewSize.Height;

        double innerFadedBorderBaseMarginThickness = settings.FadedEdgeThickness / 2.0;
        settings.InnerFadedBorder.Margin = new Thickness(innerFadedBorderBaseMarginThickness);
        settings.InnerFadedBorderEffect.Radius = settings.FadedEdgeThickness;
    }

    private static double CalculateNewMarginBasedOnOffsetFromEdge(ScrollViewer scrollViewer, double edgeOffset)
    {
        FadeSettings settings = Settings[scrollViewer];

        var innerFadedBorderBaseMarginThickness = settings.FadedEdgeThickness / 2.0;
        //var calculatedOffset = (innerFadedBorderBaseMarginThickness) - (1.0 * (this.FadedEdgeThickness - (edgeOffset / this.FadedEdgeFalloffSpeed)));

        double calculatedOffset;
        if (edgeOffset == 0)
            calculatedOffset = -innerFadedBorderBaseMarginThickness;
        else
            calculatedOffset = (edgeOffset * settings.FadedEdgeFalloffSpeed) - innerFadedBorderBaseMarginThickness;

        return Math.Min(innerFadedBorderBaseMarginThickness, calculatedOffset);
    }

    public static void OnApplyTemplate(ScrollViewer scrollViewer)
    {
        BuildInnerFadedBorderEffectForOpacityMask(scrollViewer);
        BuildInnerFadedBorderForOpacityMask(scrollViewer);
        BuildOuterFadedBorderForOpacityMask(scrollViewer);
        SetOpacityMaskOfScrollContainer(scrollViewer);
    }

    private static void BuildInnerFadedBorderEffectForOpacityMask(ScrollViewer scrollViewer)
    {
        FadeSettings settings = Settings[scrollViewer];

        settings.InnerFadedBorderEffect = new BlurEffect()
        {
            RenderingBias = RenderingBias.Performance,
        };
    }

    private static void BuildInnerFadedBorderForOpacityMask(ScrollViewer scrollViewer)
    {
        FadeSettings settings = Settings[scrollViewer];

        settings.InnerFadedBorder = new Border()
        {
            Background = Brushes.Black,
            HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch,
            VerticalAlignment = System.Windows.VerticalAlignment.Stretch,
            Effect = settings.InnerFadedBorderEffect,
        };
    }

    private static void BuildOuterFadedBorderForOpacityMask(ScrollViewer scrollViewer)
    {
        FadeSettings settings = Settings[scrollViewer];

        byte fadedEdgeByteOpacity = (byte)(settings.FadedEdgeOpacity * 255);

        settings.OuterFadedBorder = new Border()
        {
            Background = new SolidColorBrush(Color.FromArgb(fadedEdgeByteOpacity, 0, 0, 0)),
            ClipToBounds = true,
            Child = settings.InnerFadedBorder,
        };
    }

    private static void SetOpacityMaskOfScrollContainer(ScrollViewer scrollViewer)
    {
        FadeSettings settings = Settings[scrollViewer];

        var opacityMaskBrush = new VisualBrush()
        {
            Visual = settings.OuterFadedBorder
        };

        var scrollContentPresentationContainer = scrollViewer.Template.FindName(PART_SCROLL_PRESENTER_CONTAINER_NAME, scrollViewer) as UIElement;

        if (scrollContentPresentationContainer == null)
            return;

        scrollContentPresentationContainer.OpacityMask = opacityMaskBrush;

        // test
        /*var container = scrollContentPresentationContainer as Border;
        var scroller = container.Child as UIElement;
        container.Child = null;

        Grid g = new Grid();
        container.Child = g;

        g.Children.Add(scroller);
        this.OuterFadedBorder.IsHitTestVisible = false;
        g.Children.Add(this.OuterFadedBorder);*/
    }


    protected class FadeSettings
    {
        public BlurEffect InnerFadedBorderEffect { get; set; }
        public Border InnerFadedBorder { get; set; }
        public Border OuterFadedBorder { get; set; }

        public double FadedEdgeThickness { get; set; }
        public double FadedEdgeFalloffSpeed { get; set; }
        public double FadedEdgeOpacity { get; set; }

        public bool Initialized { get; set; }

        public FadeSettings()
        {
            FadedEdgeThickness = 20.0d;
            FadedEdgeFalloffSpeed = 4.0d;
            FadedEdgeOpacity = 0.0d;
        }
    }
}

您可以在代码中设置附加属性:

scroller.SetValue(ScrollViewerExtensions.FadedEdgeThicknessProperty, 70.0d);

或者直接在XAML中定义:

<ScrollViewer Name="scrollViewer" controls:ScrollViewerExtensions.FadedEdgeThickness="40">
    some content
</ScrollViewer>

希望你们能用它做点什么!

答案 2 :(得分:1)

您可以在同一网格内的ScrollViewer顶部添加一个带透明渐变的控件,并将其'IsHitTestVisible'设置为false以实现此效果。以下是使用ScrollViewer顶部的Canvas控件的示例的修改版本:

<Grid Width="200" Height="130">
            <ScrollViewer BorderThickness="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Padding="2"
                           HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Hidden"  Background="LightBlue">
                <TextBlock Margin="10,30,10,30" TextWrapping="Wrap" OpacityMask="Black" VerticalAlignment="Center">
                Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum
                </TextBlock>
            </ScrollViewer>
            <Canvas Width="200" Height="130" Focusable="False" IsEnabled="False" IsHitTestVisible="False">
                <Canvas.Background>
                    <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
                        <GradientStop Color="#FFFFFFFF" Offset="0" />
                        <GradientStop Color="#00FFFFFF" Offset="0.1" />
                        <GradientStop Color="#00FFFFFF" Offset="0.9" />
                        <GradientStop Color="#FFFFFFFF" Offset="1" />
                    </LinearGradientBrush>
                </Canvas.Background>
            </Canvas>
        </Grid>

我为ScrollViewer添加了一个背景颜色,并为TextBlock添加了一个较大的上边距,以便很容易确认所需的效果。这是输出的样子: alt text

答案 3 :(得分:1)

我今天面临同样的问题,解决方案实际上非常简单:将ScrollViewer.Background属性设置为除null之外的任何东西(在您的情况下,您需要透明),并且它可以工作。

我在这里发布答案,因为这是我发现的关于这个问题的唯一问题。

答案 4 :(得分:1)

Antoine是正确的,除非他向后退。您需要将文本块上的背景颜色设置为白色或透明或任何您想要的颜色。

 <Grid Background="LightGray">
    <ScrollViewer BorderThickness="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Padding="2"
                       HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Hidden" >
        <ScrollViewer.OpacityMask>
            <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
                <GradientStop Color="Transparent" Offset="0" />
                <GradientStop Color="Black" Offset="0.1" />
                <GradientStop Color="Black" Offset="0.9" />
                <GradientStop Color="Transparent" Offset="1" />
            </LinearGradientBrush>
        </ScrollViewer.OpacityMask>
        <TextBlock Margin="0,10"  TextWrapping="Wrap" Width="200" Background="White">
    Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum
        </TextBlock>
    </ScrollViewer>
</Grid>

如果删除TextBlock背景,您会注意到文本块中的文本将淡出,但是如果定义了背景,则仅将其应用于scrollviewer。