Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Need to understand the event-triggering in this WPF program . .

Tags:

c#

.net

wpf

I'm trying to learn SharpDX by using an example program (http://sharpdxwpf.codeplex.com/SourceControl/latest#SharpDX.WPF.sln) ... it creates a quadrant of 4 shaded triangles using 4 different approaches and it just runs by itself redrawing the graphics. It runscontinuously and seems to be event-driven because I continuously hit breakpoints in event handlers (see below) but I don't understand what triggers these events. In the XAML it has . . .

  xmlns:dxc="clr-namespace:SharpDX.WPF;assembly=SharpDX.WPF"

. . .

<dxc:DXElement Grid.Column="0" Grid.Row="0" x:Name="dxview10"/>
<Image Grid.Column="1" Grid.Row="0" x:Name="img"/>       
<dxc:DXElement Grid.Column="0" Grid.Row="1" x:Name="dxview11"/>
<dxc:DXElement Grid.Column="1" Grid.Row="1" x:Name="dxview2d"/>

. . . Where DXElement's declaration and constructor look like this . . .

public class DXElement : FrameworkElement, INotifyPropertyChanged

public DXElement()      
{         
    base.SnapsToDevicePixels = true;         
    m_renderTimer = new Stopwatch();         
    m_surface = new DXImageSource();          
    m_surface.IsFrontBufferAvailableChanged += delegate         
    {                
        UpdateReallyLoopRendering();
        if (!m_isReallyLoopRendering && m_surface.IsFrontBufferAvailable)
            Render();
        };
        IsVisibleChanged += delegate { UpdateReallyLoopRendering(); };
    }

The rest of DXElement is just brief event handlers. Here's one example:

protected override void OnRender(DrawingContext dc)
{
    dc.DrawImage(Surface, new Rect(RenderSize));
}

Notice the "override". I'm assuming that one of the parent classes of DXElement ( FrameworkElement or INotifyPropertyChanged ) are already listening for these events. But what's triggering these events? (e.g., OnRender(), OnLoopRendering(), etc) They seem to be the engine that runs the program. How can I track what causes events like this to fire in a WPF program? If I set a breakpoint at them I see them getting hit, but they're called from the framwework, e.g.,

SharpDX.WPF.dll!SharpDX.WPF.DXElement.OnRender(System.Windows.Media.DrawingContext dc) Line 153 C# PresentationCore.dll!System.Windows.UIElement.Arrange(System.Windows.Rect finalRect) Unknown PresentationFramework.dll!System.Windows.Controls.Grid.ArrangeOverride(System.Windows.Size arrangeSize) Unknown PresentationFramework.dll!System.Windows.FrameworkElement.ArrangeCore(System.Windows.Rect finalRect) Unknown PresentationCore.dll!System.Windows.UIElement.Arrange(System.Windows.Rect finalRect) Unknown PresentationFramework.dll!MS.Internal.Helper.ArrangeElementWithSingleChild(System.Windows.UIElement element, System.Windows.Size arrangeSize) Unknown PresentationFramework.dll!System.Windows.Controls.ContentPresenter.ArrangeOverride(System.Windows.Size arrangeSize) Unknown

... so I don't understand what the program is doing to make these events happen. How do I figure that out?

like image 892
user316117 Avatar asked Apr 15 '16 15:04

user316117


2 Answers

They use per-frame rendering using global CompositionTarget.Rendering event. It is get called once per frame, for all subscribers. You can read more details about it here: https://msdn.microsoft.com/en-us/library/ms748838%28v=vs.100%29.aspx.

At DXElement source code you see Renderer dependency property. In property changed handler for this property you will see how they subscribe to mentioned CompositionTarget.Rendering event if some conditions match (control is visible, not in design mode and so on). They also start Stopwatch to measure how much time has passed since the beginning, then render the frame.

As for OnRender handler you mentioned. This one is called during layout pass (when parent controls decide how to lay out their children) under some conditions. It is called once when DXElement is first rendered, then it is called when you for example resize DXElement, or call InvalidateVisual on it. But it is not called when those triangles change color in your example - this is done using CompositionTarget.Rendering event.

So short answer to your question would be - all events used in your example are triggered by WPF rendering system.

like image 151
Evk Avatar answered Nov 14 '22 22:11

Evk


A rough guess is that it is calling InvalidateVisual() from within a recurrent timer, which at some point will invoke OnRender().

like image 37
aybe Avatar answered Nov 14 '22 23:11

aybe