Role of the Visual Object

Provides support for:

  • Output display
    • Rendering the persisted, serialzied drawing content of a visual.
  • Transformations
  • Clipping
  • Hit testing
    • Detemining whether a coordinate or geometry is contained within the bounds of a visual.
  • Bounding box calculations

Not include support for non-rendering features:

  • Event handling
  • Layout
  • Styles
  • Data binding
  • Globalization

시각적 개체 클래스 계층 구조

DrawingVisual Class

A lightweight drawing class that is used to render shapes, images, or text.

It does not provide layout or event handling, which improves its runtime performance.

Ideal for backgrounds and clip art.

 

Viewport3DVisual class

 

ContainerVisual class

Used as a container for a collection of Visual Objects.

Drawing Content in Visual Objects

Drawing Content at the Visual Layer

You never directly instantiate a DrawingContext;

you can, however, acquire a drawing context from certain methods, such as:

  • DrawingOpen.Open
  • DrawingVisual.RenderOpen
// Create a DrawingVisual that contains a rectangle.
private DrawingVisual CreateDrawingVisualRectangle()
{
    var dv = new DrawingVisual();
 
    // Retrieve the DrawingContext in order to create new drawing content.
    DrawingContext dc = dv.RenderOpen();
 
    // Create a rectangle and draw it in the DrawingContext.
    Rect rect = new Rect(new Point(160, 100), new Size(320, 80));
    dc.DrawRectangle(Brushes.LightBlue, (System.Windows.Media.Pen)null, rect);
 
    // Persist the drawing content.
    dc.Close();
 
    return dv;
}

Enumerating Drawing Content at the Visual Layer

public void RetrieveDrawing(Visual v)
{
    DrawingGroup dg = VisualTreeHelper.GetDrawing(v);
    EnumDrawingGroup(dg);
}
 
// Enumerate the drawings in the DrawingGroup.
public void EnumDrawingGroup(DrawingGroup dg)
{
    DrawingCollection dc = dg.Children;
 
    // Enumerate the drawings in the DrawingCollection.
    foreach (Drawing drawing in dc)
    {
        // If the drawing is a DrawingGroup, call the function recursively.
        if (drawing is DrawingGroup group)
        {
            EnumDrawingGroup(group);
        }
        else if (drawing is GeometryDrawing)
        {
            // Perform action based on drawing type.  
        }
        else if (drawing is ImageDrawing)
        {
            // Perform action based on drawing type.
        }
        else if (drawing is GlyphRunDrawing)
        {
            // Perform action based on drawing type.
        }
        else if (drawing is VideoDrawing)
        {
            // Perform action based on drawing type.
        }
    }
}

 

How Visual Objects are Used to Build Controls

 

Visual Tree

 

Visual Rendering Behavior

 

VisualTreeHelper Class

 

Hit Testing

 

Enumerating the Visual Tree

// Enumerate all the descendants of the visual object.
static public void EnumVisual(Visual myVisual)
{
    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(myVisual); ++i)
    {
        // Retrieve child visual at specified index value.
        var childVisual = VisualTreeHelper.GetChild(myVisual, i) as Visual;
 
        // Do processing of the child visual object.
 
        // Enumerate children of the child visual object.
        EnumVisual(childVisual);
    }
}
// Returns the cached bounding box rectangle for the the specified Visual.
Rect rcBounds = VisualTreeHelper.GetContentBounds(myVisual);
 
// Return the bounding rectangle of the parent visual object and all of its descendants.
Rect rcBounds = VisualTreeHelper.GetDescendantBounds(parentVisual);

 

'.NET > WPF' 카테고리의 다른 글

WPF CustomControl  (0) 2021.08.15
Adorner  (0) 2021.08.15
Routed Event  (0) 2021.08.15
ScrollViewer Tips  (0) 2021.08.15
Save Canvas as an Image  (0) 2021.08.15

Bubbling & Tunneling

Bubbling: 일반적으로 사용되는 방식, from Child to Parent until Root!

Tunneling: 접두사로 Preview가 붙는 이벤트, from Root to Child.

 

input event routing

 

더이상 이벤트가 전파되지 않도록 막는 방법

void MyEventHandler(object sender, RoutedEventArgs e)
{
    e.Handled = true;
}

 

Custom Routed Event

MSDN

public class MyButtonSimple: Button
{
    // Create a custom routed event by first registering a RoutedEventID
    // This event uses the bubbling routing strategy
    public static readonly RoutedEvent TapEvent = EventManager.RegisterRoutedEvent(
        "Tap",
        RoutingStrategy.Bubble,
        typeof(RoutedEventHandler),
        typeof(MyButtonSimple));
 
    // Provide CLR accessors for the event
    public event RoutedEventHandler Tap
    {
        add { AddHandler(TapEvent, value); } 
        remove { RemoveHandler(TapEvent, value); }
    }
 
    // This method raises the Tap event
    void RaiseTapEvent()
    {
        var newEventArgs = new RoutedEventArgs(MyButtonSimple.TapEvent);
        RaiseEvent(newEventArgs);
    }
 
    // For demonstration purposes we raise the event when the MyButtonSimple is clicked
    protected override void OnClick()
    {
        RaiseTapEvent();
    }
}

 

'.NET > WPF' 카테고리의 다른 글

Adorner  (0) 2021.08.15
WPF Graphics Rendering  (0) 2021.08.15
ScrollViewer Tips  (0) 2021.08.15
Save Canvas as an Image  (0) 2021.08.15
LayoutTransform vs. RenderTransform  (0) 2021.08.15

RequestBringIntoView

ScrollViewer에는 내부 객체에 Focus가 되었을 때

자동으로 해당 객체를 향해 스크롤되도록 하는 기능이 있다.

이 기능을 막기 위해선 Focus될 객체에서 RequestBringIntoView라는 이벤트를 잡아

e.Handled = true;

로 처리해주면 된다.

'.NET > WPF' 카테고리의 다른 글

WPF Graphics Rendering  (0) 2021.08.15
Routed Event  (0) 2021.08.15
Save Canvas as an Image  (0) 2021.08.15
LayoutTransform vs. RenderTransform  (0) 2021.08.15
ListBox: background of selected item when not focused  (0) 2021.08.09
var rtbmp = new RenderTargetBitmap(
    (int)myCanvas.ActualWidth,
    (int)myCanvas.ActualHeight,
    96d, 96d,
    PixelFormats.Default);

rtbmp.Render(myCanvas);

using (var fs = new FileStream(sFilePath, FileMode.Create, FileAccess.Write, FileShare.None))
{
    var encoder = new JpegBitmapEncoder();
    encoder.Frames.Add(BitmapFrame.Create(rtbmp));
    encoder.Save(fs);
}

'.NET > WPF' 카테고리의 다른 글

WPF Graphics Rendering  (0) 2021.08.15
Routed Event  (0) 2021.08.15
ScrollViewer Tips  (0) 2021.08.15
LayoutTransform vs. RenderTransform  (0) 2021.08.15
ListBox: background of selected item when not focused  (0) 2021.08.09

WPF에서 레이아웃을 렌더링할 때

  • Measure: 각 엘리먼트의 DesiredSize 연산
  • Arrange: 자식 엘리먼트의 위치를 부모 엘리먼트를 기준으로 연산
  • Render: 연산된 UI를 화면에 렌더링

Transform의 이루어지는 시점

  • LayoutTransform
  • Measure
  • Arrange
  • RenderTransform
  • Render

'.NET > WPF' 카테고리의 다른 글

WPF Graphics Rendering  (0) 2021.08.15
Routed Event  (0) 2021.08.15
ScrollViewer Tips  (0) 2021.08.15
Save Canvas as an Image  (0) 2021.08.15
ListBox: background of selected item when not focused  (0) 2021.08.09

+ Recent posts