如何在数据网格控件中使用 WPF 特效并进行绘图?

3
我有一个数据网格控件,其中使用了称为FastShadow的自定义效果,类似于发光。
我希望效果在其边界外发光,所以没问题,但是当我在其上绘制另一个形状时,我不希望此形状受到影响。 在这种情况下,是绿色/蓝色矩形形状。
如您所见,这些矩形形状被发光效果变色。 没有它们后面的发光效果的那些看起来很好。

enter image description here

这里是XAML:

<Window x:Class="test.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:test"
    mc:Ignorable="d"
    Name="myMainWindow"
    SizeToContent="Width"
    DataContext="{Binding RelativeSource={RelativeSource Self}}"
    Title="Profit Tracker"
    WindowStyle="None"
    Topmost="True"
    Height="426">

    <Window.Resources>

        <Style x:Key="DataGridColumnSeparatorStyle" TargetType="DataGridCell">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate>
                        <Rectangle VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Fill="#1e90ff"/>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

        <Style x:Key="DataGridColumnAlarmStyle" TargetType="DataGridCell">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate>
                        <Rectangle VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Fill="#000000"/>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>



        <Style TargetType="{x:Type DataGrid}">
            <Setter Property="Background" Value="#FFF" />
            <Setter Property="AlternationCount" Value="2" />
            <Setter Property="BorderBrush" Value="Red" />
            <Setter Property="BorderThickness" Value="0" />
        </Style>

        <Style x:Key="RowStyleWithAlternation" TargetType="DataGridRow">
            <Setter Property="Background" Value="#141414"/>
            <Setter Property="Foreground" Value="White"/>
            <Setter Property="FontWeight" Value="Normal"/>
            <Style.Triggers>
                <Trigger Property="AlternationIndex" Value="0">
                    <Setter Property="Background" Value="#141414"/>
                </Trigger>
                <Trigger Property="AlternationIndex" Value="1">
                    <Setter Property="Background" Value="#282828"/>
                </Trigger>
                <Trigger Property="IsSelected" Value="True">
                    <Setter Property="BorderBrush" Value="Red" />
                    <Setter Property="BorderThickness" Value="1" />
                    <Setter Property="Margin" Value="-1,0,0,0" />
                </Trigger>
                <Trigger Property="IsMouseOver" Value="True">
                    <!--<Setter Property="BorderBrush" Value="#2eff00" />
                    <Setter Property="BorderThickness" Value="1" />-->
                    <Setter Property="Background" Value="Orange"/>
                    <!--<Setter Property="Margin" Value="-1,0,0,0" />-->
                </Trigger>
            </Style.Triggers>
        </Style>

        <Style TargetType="DataGridCell">
            <Setter Property="TextBlock.TextAlignment" Value="Center" />
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type DataGridCell}">
                        <Grid Background="{TemplateBinding Background}">
                            <ContentPresenter VerticalAlignment="Stretch"/>
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
            <Setter Property="VerticalAlignment" Value="Stretch"/>
            <Setter Property="Padding" Value="0"/>
            <Setter Property="Margin" Value="0"/>
            <Setter Property="BorderThickness" Value="0"/>
            <Setter Property="FocusVisualStyle" Value="{x:Null}" />

            <Style.Triggers>
                <Trigger Property="IsSelected" Value="True">
                    <Setter Property="BorderBrush" Value="#1e90ff" />
                    <Setter Property="BorderThickness" Value="1" />
                    <!--<Setter Property="Background" Value="Red"/>-->
                </Trigger>



                <MultiDataTrigger>
                    <MultiDataTrigger.Conditions>
                        <Condition Binding="{Binding Column.DisplayIndex, RelativeSource={RelativeSource Self}}" Value="4"/>
                    </MultiDataTrigger.Conditions>
                    <MultiDataTrigger.Setters>
                        <Setter Property="VerticalAlignment" Value="Stretch"/>
                    </MultiDataTrigger.Setters>
                </MultiDataTrigger>

                <Trigger Property="IsSelected" Value="True">
                    <Setter Property="Background" Value="{x:Null}"/>
                    <Setter Property="BorderBrush" Value="{x:Null}"/>
                </Trigger>
            </Style.Triggers>
        </Style>

        <Style TargetType="DataGridColumnHeader">
            <Setter Property="HorizontalContentAlignment" Value="Center" />
        </Style>

        <Style TargetType="{x:Type ProgressBar}">
            <Setter Property="Padding" Value="0"/>
            <Setter Property="Margin" Value="0"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="ProgressBar">
                        <Border BorderThickness="1" Background="#006400" CornerRadius="0" Padding="0">
                            <Grid x:Name="PART_Track">
                                <Rectangle x:Name="PART_Indicator" HorizontalAlignment="Left" Fill="#75001D" />
                            </Grid>
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

        <CollectionViewSource Source="{Binding Coins}" IsLiveSortingRequested="True" x:Key="MyKey" />

    </Window.Resources>

    <Grid>

        <Grid.LayoutTransform>
            <ScaleTransform ScaleX="{Binding ViewScale, ElementName=myMainWindow}" ScaleY="{Binding ViewScale, ElementName=myMainWindow}" />
        </Grid.LayoutTransform>

        <DataGrid Name="dataGrid" ItemsSource="{Binding Source={StaticResource MyKey}}" SelectionMode="Single" GridLinesVisibility="None" HorizontalScrollBarVisibility="Hidden" RowHeaderWidth="0" IsReadOnly="True" CanUserAddRows="False" CanUserResizeColumns="False" CanUserResizeRows="False" AutoGenerateColumns="False" RowStyle="{StaticResource RowStyleWithAlternation}">
            <DataGrid.Resources>
                <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Transparent" />
                <SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="Transparent" />
            </DataGrid.Resources>

            <DataGrid.Columns>

                <DataGridTemplateColumn Header="" MaxWidth="40">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>

                            <Grid>
                            <Grid Visibility="{Binding IsVisible}">

                                <Border Margin="1" VerticalAlignment="Stretch" BorderThickness="0" Background="#ffff00" HorizontalAlignment="Left" Width="7">
                                    <local:FastShadow Color="Yellow" ShadowDepth="0" Direction="0" BlurRadius="80" Opacity="0.2">
                                    </local:FastShadow>
                                </Border>

                                <Border Margin="1" VerticalAlignment="Stretch" BorderThickness="0" Background="#ffff00" HorizontalAlignment="Left" Width="7">
                                    <local:FastShadow Color="#ff8d0a" ShadowDepth="0" Direction="0" BlurRadius="80" Opacity="0.4">
                                    </local:FastShadow>
                                </Border>

                                <Border BorderBrush="#ff8d0a" BorderThickness="1" CornerRadius="3" Background="#ffff00">
                                    <Border Margin="1" BorderBrush="#fff533" BorderThickness="4" CornerRadius="3" ClipToBounds="False" HorizontalAlignment="Stretch">
                                        <Border.Effect>
                                            <BlurEffect Radius="50"/>
                                        </Border.Effect>
                                    </Border>
                                </Border>
                            </Grid>

                                <Grid Height="5" VerticalAlignment="Bottom">
                                    <Grid Background="GreenYellow">
                                        <Rectangle Fill="DarkGreen" HorizontalAlignment="Right" Width="50">
                                        </Rectangle>
                                    </Grid>
                                    <Grid >
                                        <Rectangle Fill="DarkBlue" HorizontalAlignment="Right" Width="20">
                                        </Rectangle>
                                    </Grid>
                                </Grid>

                            </Grid>
                            
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>

                <DataGridTemplateColumn MinWidth="0" Width="2" CellStyle="{StaticResource DataGridColumnSeparatorStyle}"/>

                <DataGridTemplateColumn Header="" Width="24">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <Ellipse Width="8" Height="8" Fill="Blue" />
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>



                <DataGridTextColumn Header="" Width="60"/>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Window>

代码:

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace test
{
    public partial class MainWindow : Window, INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        protected void SetField<T> ( ref T field, T value, string propertyName )
        {
            if ( !EqualityComparer<T>.Default.Equals ( field, value ) )
            {
                field = value;
                PropertyChanged?.Invoke ( this, new PropertyChangedEventArgs ( propertyName ) );
            }
        }


        decimal viewScale = 1;
        public decimal ViewScale
        {
            get => this.viewScale;
            set => SetField ( ref this.viewScale, value,
                "ViewScale"
                );
        }

        ObservableCollection<Coin> _coins;
        public ObservableCollection<Coin> Coins { get => _coins; set => SetField ( ref _coins, value, nameof ( _coins ) ); }
        public ICollectionView CollectionView;

        public MainWindow ( )
        {
            this.Coins = new ObservableCollection<Coin> ( );
            for ( int i = 0; i < 25; ++i )
                this.Coins.Add ( new Coin ( "Coin 1", i ) );

            this.Coins [ 1 ].IsVisible = Visibility.Visible;
            this.Coins [ 4 ].IsVisible = Visibility.Visible;
            this.Coins [ 7 ].IsVisible = Visibility.Visible;

            this.DataContext = this;

            InitializeComponent ( );

            this.PreviewKeyDown += MainWindow_PreviewKeyDown;
            this.MouseLeftButtonDown += MainWindow_MouseLeftButtonDown;
        }

        private void MainWindow_MouseLeftButtonDown ( object sender, MouseButtonEventArgs e )
        {
            if ( ( Keyboard.Modifiers & ModifierKeys.Alt ) == ModifierKeys.Alt )
                DragMove ( );
        }

        void MainWindow_PreviewKeyDown ( object sender, KeyEventArgs e )
        {
            if ( e.Key == Key.Home )
            {
                this.dataGrid.ScrollIntoView ( this.dataGrid.Items [ 0 ] );
            }
            if ( e.Key == Key.End )
            {
                this.dataGrid.ScrollIntoView ( this.dataGrid.Items [ this.dataGrid.Items.Count - 1 ] );
                this.dataGrid.UpdateLayout ( );
                this.dataGrid.ScrollIntoView ( this.dataGrid.Items [ 0 ] );
            }
            else if ( e.Key == Key.F12 )
            {
                this.ViewScale += 0.1m;
            }
        }
    }

    public class Coin
    {
        public string Symbol { get; set; }
        public int PNL { get; set; }
        public SolidColorBrush Color2 { get; set; }

        public Visibility IsVisible { get; set; }

        public Coin ( string symbol, int pnl )
        {
            this.Symbol = symbol;
            this.PNL = pnl;

            Random rnd = new Random ( );
            Color c = Color.FromRgb ( ( byte ) rnd.Next ( 256 ), ( byte ) rnd.Next ( 256 ), ( byte ) rnd.Next ( 256 ) );

            this.Color2 = new SolidColorBrush ( c );

            this.IsVisible = Visibility.Hidden;
        }
    }
}

FastShadow类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace test
{
    using System.Windows.Shapes;
    using System.Windows.Controls;
    using System.Windows;
    using System.Windows.Media;
    using System;
    using System.ComponentModel;

    /// <summary>
    /// Emulates the System.Windows.Media.Effects.DropShadowEffect using
    /// rectangles and gradients, which performs a million times better
    /// and won't randomly crash a good percentage of your end-user's 
    /// video drivers.
    /// </summary>
    public class FastShadow : Decorator
    {

        #region Dynamic Properties

        public static readonly DependencyProperty ColorProperty =
                DependencyProperty.Register (
                        "Color",
                        typeof ( Color ),
                        typeof ( FastShadow ),
                        new FrameworkPropertyMetadata (
                                Color.FromArgb ( 0x71, 0x00, 0x00, 0x00 ),
                                FrameworkPropertyMetadataOptions.AffectsRender ) );

        /// <summary>
        /// The Color property defines the Color used to fill the shadow region. 
        /// </summary> 
        [Category ( "Common Properties" )]
        public Color Color
        {
            get { return ( Color ) GetValue ( ColorProperty ); }
            set { SetValue ( ColorProperty, value ); }
        }

        /// <summary>
        /// Distance from centre, why MS don't call this "distance" beats
        /// me.. Kept same as other Effects for consistency.
        /// </summary>
        [Category ( "Common Properties" ), Description ( "Distance from centre" )]
        public double ShadowDepth
        {
            get { return ( double ) GetValue ( ShadowDepthProperty ); }
            set { SetValue ( ShadowDepthProperty, value ); }
        }

        // Using a DependencyProperty as the backing store for ShadowDepth.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ShadowDepthProperty =
            DependencyProperty.Register ( "ShadowDepth", typeof ( double ), typeof ( FastShadow ),
            new FrameworkPropertyMetadata (
                5.0, FrameworkPropertyMetadataOptions.AffectsRender,
                    new PropertyChangedCallback ( ( o, e ) =>
                    {
                        FastShadow f = o as FastShadow;
                        if ( ( double ) e.NewValue < 0 )
                            f.ShadowDepth = 0;
                    } ) ) );


        /// <summary>
        /// Size of the shadow
        /// </summary>
        [Category ( "Common Properties" ), Description ( "Size of the drop shadow" )]
        public double BlurRadius
        {
            get { return ( double ) GetValue ( BlurRadiusProperty ); }
            set { SetValue ( BlurRadiusProperty, value ); }
        }

        // Using a DependencyProperty as the backing store for BlurRadius.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty BlurRadiusProperty =
            DependencyProperty.Register ( "BlurRadius", typeof ( double ), typeof ( FastShadow ),
            new FrameworkPropertyMetadata ( 10.0,
                FrameworkPropertyMetadataOptions.AffectsRender,
                    new PropertyChangedCallback ( ( o, e ) =>
                    {
                        FastShadow f = o as FastShadow;
                        if ( ( double ) e.NewValue < 0 )
                            f.BlurRadius = 0;
                    } ) ) );


        /// <summary>
        /// Angle of the shadow
        /// </summary>
        [Category ( "Common Properties" ), Description ( "Angle of the shadow" )]
        public int Direction
        {
            get { return ( int ) GetValue ( DirectionProperty ); }
            set { SetValue ( DirectionProperty, value ); }
        }

        // Using a DependencyProperty as the backing store for Direction.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty DirectionProperty =
            DependencyProperty.Register ( "Direction", typeof ( int ), typeof ( FastShadow ),
            new FrameworkPropertyMetadata ( 315, FrameworkPropertyMetadataOptions.AffectsRender ) );


        #endregion Dynamic Properties

        #region Protected Methods

        protected override void OnRender ( DrawingContext drawingContext )
        {

            double distance = Math.Max ( 0, ShadowDepth );
            double blurRadius = Math.Max ( BlurRadius, 0 );
            double angle = Direction + 45; // Make it behave the same as DropShadowEffect

            Rect shadowBounds = new Rect ( new Point ( 0, 0 ),
                             new Size ( RenderSize.Width, RenderSize.Height ) );

            shadowBounds.Inflate ( blurRadius, blurRadius );

            Color color = Color;

            // Transform angle for "Direction"
            double angleRad = angle * Math.PI / 180.0;
            double xDispl = distance;
            double yDispl = distance;
            double newX = xDispl * Math.Cos ( angleRad ) - yDispl * Math.Sin ( angleRad );
            double newY = yDispl * Math.Cos ( angleRad ) + xDispl * Math.Sin ( angleRad );

            TranslateTransform translate = new TranslateTransform ( newX, newY );
            Rect transformed = translate.TransformBounds ( shadowBounds );

            // Hint: you can make the blur radius consume more "centre"
            //       region of the bounding box by doubling this here
            // blurRadius = blurRadius * 2;

            // Build a set of rectangles for the shadow box
            Rect [ ] edges = new Rect [ ] {
                new Rect(new Point(transformed.X,transformed.Y), new Size(blurRadius,blurRadius)), // TL
                new Rect(new Point(transformed.X+blurRadius,transformed.Y), new Size(Math.Max(transformed.Width-(blurRadius*2),0),blurRadius)), // T
                new Rect(new Point(transformed.Right-blurRadius,transformed.Y), new Size(blurRadius,blurRadius)), // TR
                new Rect(new Point(transformed.Right-blurRadius,transformed.Y+blurRadius), new Size(blurRadius,Math.Max(transformed.Height-(blurRadius*2),0))), // R
                new Rect(new Point(transformed.Right-blurRadius,transformed.Bottom-blurRadius), new Size(blurRadius,blurRadius)), // BR
                new Rect(new Point(transformed.X+blurRadius,transformed.Bottom-blurRadius), new Size(Math.Max(transformed.Width-(blurRadius*2),0),blurRadius)), // B
                new Rect(new Point(transformed.X,transformed.Bottom-blurRadius), new Size(blurRadius,blurRadius)), // BL
                new Rect(new Point(transformed.X,transformed.Y+blurRadius), new Size(blurRadius,Math.Max(transformed.Height-(blurRadius*2),0))), // L
                new Rect(new Point(transformed.X+blurRadius,transformed.Y+blurRadius), new Size(Math.Max(transformed.Width-(blurRadius*2),0),Math.Max(transformed.Height-(blurRadius*2),0))), // C
            };

            // Gradient stops look a lot prettier than
            // a perfectly linear gradient..
            GradientStopCollection gsc = new GradientStopCollection ( );
            Color stopColor = color;
            stopColor.A = ( byte ) ( color.A );
            gsc.Add ( new GradientStop ( color, 0.0 ) );
            stopColor.A = ( byte ) ( .74336 * color.A );
            gsc.Add ( new GradientStop ( stopColor, 0.1 ) );
            stopColor.A = ( byte ) ( .38053 * color.A );
            gsc.Add ( new GradientStop ( stopColor, 0.3 ) );
            stopColor.A = ( byte ) ( .12389 * color.A );
            gsc.Add ( new GradientStop ( stopColor, 0.5 ) );
            stopColor.A = ( byte ) ( .02654 * color.A );
            gsc.Add ( new GradientStop ( stopColor, 0.7 ) );
            stopColor.A = ( byte ) ( 0 );
            gsc.Add ( new GradientStop ( stopColor, 0.9 ) );

            gsc.Freeze ( );

            Brush [ ] colors = new Brush [ ]{
                // TL
                new RadialGradientBrush(gsc){ Center = new Point(1, 1), GradientOrigin = new Point(1, 1), RadiusX=1, RadiusY=1},
                // T
                new LinearGradientBrush(gsc, 0){ StartPoint = new Point(0,1), EndPoint=new Point(0,0)},
                // TR
                new RadialGradientBrush(gsc){ Center = new Point(0, 1), GradientOrigin = new Point(0, 1), RadiusX=1, RadiusY=1},
                // R
                new LinearGradientBrush(gsc, 0){ StartPoint = new Point(0,0), EndPoint=new Point(1,0)},
                // BR
                new RadialGradientBrush(gsc){ Center = new Point(0, 0), GradientOrigin = new Point(0, 0), RadiusX=1, RadiusY=1},
                // B
                new LinearGradientBrush(gsc, 0){ StartPoint = new Point(0,0), EndPoint=new Point(0,1)},
                // BL
                new RadialGradientBrush(gsc){ Center = new Point(1, 0), GradientOrigin = new Point(1, 0), RadiusX=1, RadiusY=1},
                // L
                new LinearGradientBrush(gsc, 0){ StartPoint = new Point(1,0), EndPoint=new Point(0,0)},
                // C
                new SolidColorBrush(color),
            };

            // This is a test pattern, uncomment to see how I'm drawing this
            //Brush[] colors = new Brush[]{
            //    Brushes.Red,
            //    Brushes.Green,
            //    Brushes.Blue,
            //    Brushes.Fuchsia,
            //    Brushes.Gainsboro,
            //    Brushes.LimeGreen,
            //    Brushes.Navy,
            //    Brushes.Orange,
            //    Brushes.White,
            //};
            double [ ] guidelineSetX = new double [ ] { transformed.X,
                                                    transformed.X+blurRadius,
                                                    transformed.Right-blurRadius,
                                                    transformed.Right};

            double [ ] guidelineSetY = new double [ ] { transformed.Y,
                                                    transformed.Y+blurRadius,
                                                    transformed.Bottom-blurRadius,
                                                    transformed.Bottom};

            drawingContext.PushGuidelineSet ( new GuidelineSet ( guidelineSetX, guidelineSetY ) );
            for ( int i = 0; i < edges.Length; i++ )
            {
                drawingContext.DrawRoundedRectangle ( colors [ i ], null, edges [ i ], 0.0, 0.0 );
            }
            drawingContext.Pop ( );
        }

        #endregion

    }
}

你尝试过提高z-index吗?<Grid Height="5" VerticalAlignment="Bottom" Panel.ZIndex="10">[...]</Grid> - T.Schwarz
效果适用于应用它们的任何内容。将其应用于容器,其中的任何控件都将获得该效果。你发布了那么多内容,我看不到你的效果在哪里。但是正确的方法是将效果应用于其他东西,比如一个填充所需效果空间的矩形,但不包含其他内容。 - Andy
@T.Schwarz:谢谢,我刚试了一下,它看起来还是一样的。发光出现在矩形的顶部。 - Joan Venge
@ Andy:谢谢,但我的矩形超出了应用效果的容器范围。这就是为什么我不明白它为什么没有出现在应用效果的顶部。 - Joan Venge
我认为你混淆了装饰和效果。 装饰是基于Decorator类的。 它位于AdornerLayer上方,覆盖所有内容元素。 而效果是元素本身的视觉组件。 它们是基于Effect类创建的。 效果被分配给UIElement.Effect属性。 - EldHasp
渲染发生在测量和排列之后,因此它将在表面的任何位置呈现(除非被剪切)。如果您在元素框之外进行渲染,则会在其他元素上绘制。您应该以不同方式组合您的元素(几乎总是使用WPF覆盖OnRender是一个坏迹象),使用效果或位图效果(已弃用,速度较慢,因为它不使用GPU,但比编写像素着色器更容易)。 - Simon Mourier
2个回答

1

装饰基于Decorator类,位于所有内容元素上方的AdornerLayer中。

更改FastShadow的基类:使用Effect(或其派生类)而不是Decorator。
将FastShadow类的一个实例分配给Effect属性。


装饰器当然更快,因为它缺乏任何逻辑并且在很大程度上忽略了布局。如果您想要离开装饰器,则其呈现逻辑必须考虑底层元素的实际布局。 - EldHasp
我暂时无法帮忙提供示例代码 - 我没有足够的空闲时间。 也许明天或后天会有更多时间,届时我可以做到。 - EldHasp
我更仔细地查看了FastShadow代码。 在它的OnRender方法中,你正在元素本身之外进行绘制。 这是可以理解的,因为你想要获得辐射。 但是我不清楚你希望这种辐射如何影响其他元素。 你能否通过图示演示你想要实现的效果? - EldHasp
谢谢,是的,我想要的效果是发光,但我想在其上方绘制一个矩形形状,该形状不受效果影响,就像新的 Photoshop 图层一样位于发光效果之上。我使用矩形形状是为了其他目的,因此它不是发光效果的一部分。如果我将矩形放在发光效果下面,我希望它会受到发光效果的影响,但如果它位于发光效果之上,则不会受到影响。 - Joan Venge
但是发光能否绘制在网格外面呢?由于发光从单元格向外辐射,它会溢出单元格的可见边界。 - Joan Venge
显示剩余6条评论

1
我不确定你是否注意到(或者这是有意的),但“发光”只影响高一些的行,而不是更低的行。在你的截图中很难看出,但如果增加发光效果的强度,就会变得清晰。例如,第7行上的“coin”会产生一个发光效果,覆盖了上面两三行,但是第8行或以下根本没有发光效果。这似乎与每个连续行具有比上一行更高的z-index有关,因此第8行会渲染在已经渲染的发光效果之上,这也是为什么你目前的解决方案可能难以解决的另一个原因!
我怀疑数据网格的奇怪可视树将阻止您使用当前解决方案实现所需的结果:您无法拥有跨多个网格行渲染的发光效果,并且出现在行内容(绿色和蓝色长方形)后面,因此您可能需要从不同的角度来考虑这个问题。虽然我没有具体的解决方案,但我建议探索一种在数据网格后面绘制发光效果的方法(例如使用画布)。
这意味着数据网格行当然需要具有透明的背景颜色,因此您可能需要重新考虑如何实现交替的行颜色。
当您将发光效果添加到画布上时(可能只是具有线性渐变背景的边框控件),您需要知道将其放置在哪里(即Canvas.Top),以确保它出现在正确的数据行后面。如果所有行具有相同的固定高度,则这应该是一个微不足道的计算。
画布必须与数据网格“同步”滚动,因为用户滚动后者,确保画布上的发光效果(边框控件)保持在其各自行后面。我认为您需要将画布放置在ScrollViewer内,然后从数据网格的滚动事件处理程序中操作其滚动位置。您可能会发现其他SO文章详细介绍如何检测滚动(以及滚动多少)。
不用说,您必须在代码后台中完成所有这些工作,而不能仅使用XAML!

谢谢,我知道这个问题,我已经提了一个问题,但没有回复。你的建议听起来需要很多工作,但也有可能会影响性能,所以我认为最好的办法是使用常规的 dropshadow,因为据我所知它没有这个问题。 - Joan Venge

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接