Table of Contents

Class SplitPane

Namespace
Icy.UI.Controls
Assembly
IcyUI.dll

Splits a region into two resizable areas (First/Second) separated by a draggable divider.

public class SplitPane : Control, INotifyPropertyChanging, IBindingTarget, INotifyPropertyChanged, INotifyFocusChanged, IContainerLayout
Inheritance
SplitPane
Implements
Inherited Members
Extension Methods

Remarks

Divider-grab is via OnDragStarted(Point)/OnDragPerforming(Point) - the same single-target "hold and move the pointer" mechanism Slider's thumb uses, not the cross-container IDragSource/IDropTarget framework - a resize gesture has no drop target elsewhere.

Exactly two panes and one Orientation per instance - a 3+ region layout is built by nesting SplitPanes, not a native N-pane mode.

Template-safe via a named template part: a Template that declares an element named PART_Divider (of any type assignable to Border) has drag logic and DividerBrush wired to it instead of the built-in default divider - see OnApplyTemplate().

Constructors

SplitPane()

Initializes a new instance of the SplitPane class.

public SplitPane()

Properties

DividerBrush

Gets or sets the brush used to paint the divider's visible line - the currently-live one (the default built-in line, or a Template's own PART_Divider once OnApplyTemplate() has repointed it).

public IBrush DividerBrush { get; set; }

Property Value

IBrush

DividerSize

Gets or sets the divider's hit-test band width, in pixels along Orientation's axis - the grabbable area is this wide even though the visible line drawn inside it is thinner (see DividerBrush).

public float DividerSize { get; set; }

Property Value

float

First

Gets or sets the element displayed before the divider (left, when Orientation is Horizontal; top, when Vertical).

public UIElement? First { get; set; }

Property Value

UIElement

MinFirstSize

Gets or sets the minimum size, in pixels along Orientation's axis, First keeps regardless of SplitterPosition.

public float MinFirstSize { get; set; }

Property Value

float

MinSecondSize

Gets or sets the minimum size, in pixels along Orientation's axis, Second keeps regardless of SplitterPosition.

public float MinSecondSize { get; set; }

Property Value

float

Orientation

Gets or sets the axis First/Second are split along.

public Orientation Orientation { get; set; }

Property Value

Orientation

Remarks

Matches Orientation's own semantics: Horizontal places First/Second side-by-side (a vertical-line divider); Vertical stacks them (a horizontal-line divider).

Second

Gets or sets the element displayed after the divider (right, when Orientation is Horizontal; bottom, when Vertical).

public UIElement? Second { get; set; }

Property Value

UIElement

SplitterPosition

Gets or sets the fraction (0-1) of available space, along Orientation's axis, allocated to First.

[BindingOverride(BindingMode.TwoWay)]
public float SplitterPosition { get; set; }

Property Value

float

Remarks

Clamped to [0,1] only - MinFirstSize/MinSecondSize are enforced separately, at arrange/drag time, since they depend on the control's current size (see ArrangeContent()).

Methods

ArrangeContent()

Handles custom arrange logic when overridden in any UIElement instance.

protected override void ArrangeContent()

Remarks

This method is called during the arrange pass to position and size the element's content within its final bounds. The element's position and size are already determined by the layout system and available in the ActualBounds property.

When implementing this method:

  • Position child elements within the available space;
  • Respect the element's padding when positioning content;
  • Handle any content-specific layout requirements;
  • Call Arrange() on child elements if needed.

GetDragAxes(in DragClaimContext)

Returns the axes along which this element wants to own a drag that starts on it or a descendant.

protected override DragAxes GetDragAxes(in DragClaimContext context)

Parameters

context DragClaimContext

The starting drag.

Returns

DragAxes

The claimed axes; the base implementation returns None.

Remarks

When a drag starts, Canvas asks the hit element and each ancestor in turn. The innermost element whose answer contains the drag's main axis (the larger component of LocalDirection) owns the gesture. If none does, the innermost element with any answer owns it. Only the owner receives OnDragStarted(Point), OnDragPerforming(Point), OnDragFling(Vector2) and OnDragEnded(Point).

An element that handles drags must override this method: overriding OnDragStarted(Point) alone receives nothing.

GetVisualChildren()

Enumerates this element's immediate visual children, in paint order (back-to-front), for hit-testing and tree traversal.

protected override IEnumerable<UIElement> GetVisualChildren()

Returns

IEnumerable<UIElement>

The element's immediate children. The base implementation yields none (a leaf element).

Remarks

Container elements (e.g. Panel, Border) override this to expose their children, in the exact order they're drawn in — HitTest(Vector2) depends on this matching actual paint order, or clicks will target the wrong, visually-obscured element.

MeasureContent()

Handles custom measure logic when overridden in any UIElement instance.

protected override Size MeasureContent()

Returns

Size

Size recommended to display the UIElement.

Remarks

This method is called during the measure pass to determine the desired size of the element. The returned size should represent the natural size of the element's content, without considering any constraints, margins, or padding.

When implementing this method:

  • Return the natural size needed to display the content;
  • Do not include padding, margins, or borders in the returned size;
  • Consider the content's actual dimensions (e.g., text length, image size);
  • Return Empty if the element has no content.

OnApplyTemplate()

Called once, every time Template changes (in either direction - applied, cleared, or switched to a different template), right after Chrome and every decoration/content property have been fully re-wired for the new state.

protected override void OnApplyTemplate()

Remarks

Does nothing by default. A subclass that reaches into its own visual tree by reference - e.g. Slider wiring its drag logic directly to its thumb element - overrides this to call GetTemplateChild<T>(string) and repoint that reference to whatever the new Template (or, when reverting, the fresh default Border) actually provides, instead of hardcoding it once at construction. This is what actually makes a control "template-safe": until a control overrides this appropriately, applying a custom Template to it silently orphans whatever elements its own code still holds direct references to.

OnDragEnded(Point)

Invoked by Canvas when a drag sequence owned by this element (see GetDragAxes(in DragClaimContext)) has ended - released or canceled. The base implementation does nothing.

protected override void OnDragEnded(Point screenPoint)

Parameters

screenPoint Point

The drag's ending position, in screen/window space.

OnDragPerforming(Point)

Invoked by Canvas whenever the pointer moves during a drag sequence owned by this element (see GetDragAxes(in DragClaimContext)). The base implementation does nothing.

protected override void OnDragPerforming(Point screenPoint)

Parameters

screenPoint Point

The drag's current position, in screen/window space.

OnDragStarted(Point)

Invoked by Canvas when a drag sequence starts and this element owns it (see GetDragAxes(in DragClaimContext); overriding this method alone receives nothing). The base implementation does nothing.

protected override void OnDragStarted(Point screenPoint)

Parameters

screenPoint Point

The drag's starting position, in screen/window space.

Remarks

Only starts tracking the drag when screenPoint actually landed on the divider band. GetDragAxes(in DragClaimContext) already limits ownership to divider presses; the check stays as a guard.

OnRender(IRenderContext)

Handles custom render logic when overridden in any UIElement instance.

protected override void OnRender(IRenderContext context)

Parameters

context IRenderContext

The context to render with.

Events

SplitterPositionChanged

Occurs when SplitterPosition changes.

public event EventHandler? SplitterPositionChanged

Event Type

EventHandler