简体   繁体   English

WPF DrawingContext在我的对象后面绘制

[英]WPF DrawingContext draw behind my objects

I have a canvas with some images, and i'm also using DrawGeometry, to draw a circle that is filling when the time is passing. 我有一个带有一些图像的画布,我也在使用DrawGeometry来绘制一个在时间过去时填充的圆圈。

This is how i draw the circle in my DrawingContext: 这就是我在DrawingContext中绘制圆圈的方法:

protected override void OnRender(DrawingContext drawingContext)
{
    base.OnRender(drawingContext);
    MyUtils.RenderProgressClock(drawingContext, clockPosition, 50, gameTime / totalTime);
}

And calling the InvalidateVisual(); 并调用InvalidateVisual(); to call it. 打电话给它。

But Doing this my circle is behind my images and i cant see it, how can i draw it infront of them? 但是这样做我的圈子是我的图像背后,我无法看到它,我怎么能在它们面前画出来?

Im totally new to WPF and its giving me a hard Time.... 我是WPF的新手,它给了我一个艰难的时间....

This is the other method code as requested: 这是所请求的其他方法代码:

 private static PathGeometry GetClockGeometry(Point position, double percentage, double radius)
        {
            const double innerFactor = 0.90;
            double innerRadius = radius * innerFactor;

            PathGeometry pie = new PathGeometry();

            PathFigure pathFigure = new PathFigure();
            pathFigure.StartPoint = new Point(0, -innerRadius);
            pathFigure.IsClosed = true;

            if (percentage > kMaxClockPercentage)
            {
                percentage = kMaxClockPercentage;
            }
            double angle = 360.0 * percentage;

            // Starting Point
            LineSegment inOutLine = new LineSegment(new Point(0, -radius), true);

            // Arc
            ArcSegment outerArc = new ArcSegment();

            outerArc.IsLargeArc = angle >= 180.0;
            outerArc.Point = new Point(Math.Cos((angle - 90) * Math.PI / 180.0) * radius, Math.Sin((angle - 90) * Math.PI / 180.0) * radius);
            outerArc.Size = new Size(radius, radius);
            outerArc.SweepDirection = SweepDirection.Clockwise;

            LineSegment outInLine = new LineSegment(new Point(outerArc.Point.X * innerFactor, outerArc.Point.Y * innerFactor), true);

            ArcSegment innerArc = new ArcSegment();
            innerArc.IsLargeArc = angle >= 180.0;
            innerArc.Point = pathFigure.StartPoint;
            innerArc.Size = new Size(innerRadius, innerRadius);
            innerArc.SweepDirection = SweepDirection.Counterclockwise;

            pathFigure.Segments.Add(inOutLine);
            pathFigure.Segments.Add(outerArc);
            pathFigure.Segments.Add(outInLine);
            pathFigure.Segments.Add(innerArc);

            pie.Transform = new TranslateTransform(position.X, position.Y);
            pie.Figures.Add(pathFigure);

            return pie;
        }

OK, now that I understand a little better what is going on, I see that my initial answer won't directly work for you. 好了,既然我现在了解的情况好一点,我看到我的初步答案不会直接对你有用。 However, I also see that you have a bit of a problem. 但是,我也看到你有点问题。

Just the general nature of the way OnRender works means that what you draw is always going to end up behind the images and whatnot that you add to the window. 只是OnRender工作方式的一般性意味着你绘制的内容总是最终会落在图像后面,以及你添加到窗口中的内容。

Add to that the fact that you're putting all this drawing code for a specific feature (the progress clock) into the window itself, and this solution feels a little off. 除此之外,您将所有这些特定功能(进度时钟)的绘图代码放入窗口本身,这个解决方案感觉有些偏差。

You might want to explore some alternatives. 您可能想要探索一些替代方案。

A simple one would be to create a UserControl to draw the Clock. 一个简单的方法是创建一个UserControl来绘制Clock。 That UserControl could have a DependencyProperty for the % that it should be filled. UserControl可能具有应该填充的%的DependencyProperty。 You could use your (roughly) same OnRender code in the UserControl or you could do it some other fancy ways (I'm sure there's some way to do it in all XAML, though I don't know it off the top of my head). 您可以在UserControl中使用(大致)相同的OnRender代码,或者您可以使用其他一些奇特的方式(我确信在所有XAML中都有一些方法可以做到这一点,尽管我不知道它在我的头脑中)。 Then you just put that clock into the window like all your other images/controls. 然后你就像所有其他图像/控件一样将时钟放入窗口。

You could also do it creating a CustomControl, though that takes a little bit more knowledge about WPF and Resources and whatnot to understand how it works. 你也可以创建一个CustomControl,虽然这需要更多关于WPF和资源的知识,以及如何理解它是如何工作的。 Since you're new to WPF, that might be a bit much right now. 由于你是WPF的新手,现在可能有点儿了。

You need to show us how your circle is added to the Canvas. 您需要向我们展示如何将圆圈添加到“画布”中。

WPF is a retained drawing system, so the order the controls appear in it's visual-tree dictates their stacking order.. OnRender() really means AccumulateDrawingObjects() as it doesn't directly draw, it just creates a set of objects to draw. WPF是一个保留的绘图系统,因此控件在其可视树中出现的顺序决定了它们的堆叠顺序OnRender()实际上意味着AccumulateDrawingObjects()因为它不直接绘制,它只是创建一组要绘制的对象。

Also, you don't need to InvalidateVisual() if an object is staying the same size, as it causes a very expensive re-layout. 此外,如果对象保持相同的大小,则不需要InvalidateVisual() ,因为它会导致非常昂贵的重新布局。

More efficient ways to re-render are to use a DependencyProperty with AffectsRender ... Or to create a DrawingGroup , add it to the DrawingContext during OnRender() , then anytime later you can DrawingGroup.Open() to change the drawing commands in the DrawingGroup . 更有效的重新渲染方法是使用DependencyProperty和AffectsRender ...或者创建一个DrawingGroup ,在OnRender()期间将它添加到DrawingContext ,然后随时可以使用DrawingGroup.Open()来更改绘图命令。 DrawingGroup

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

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