A modern and flexible WPF screen splitting library for dynamic pane management. Create resizable, dockable panels with intuitive split controls and visual feedback.
$ dotnet add package FlexiPaneA modern and flexible WPF screen splitting library for dynamic pane management. Create resizable, dockable panels with intuitive split controls and visual feedback.
<div align="center"> <img src="images/Screenshot1.png" alt="FlexiPane Split Layout" width="49%" /> <img src="images/Screenshot2.png" alt="FlexiPane Split Mode" width="49%" />Left: Multiple panels with complex split layout | Right: Interactive split mode with visual guides
</div><flexiPane:FlexiPanel /> in XAMLInstall-Package FlexiPane.WPF
dotnet add package FlexiPane.WPF
<PackageReference Include="FlexiPane.WPF" Version="1.0.0" />
Add the namespace to your XAML:
xmlns:flexiPane="clr-namespace:FlexiPane.Controls;assembly=FlexiPane"
Use the simplest possible configuration for basic split functionality:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<!-- Control Panel -->
<StackPanel Grid.Row="0" Orientation="Horizontal" Margin="10">
<ToggleButton x:Name="ModeToggleButton" Content="Toggle Split Mode" Padding="10,5" />
</StackPanel>
<!-- FlexiPanel with Event-Driven Content -->
<flexiPane:FlexiPanel
x:Name="FlexiPanel"
Grid.Row="1"
IsSplitModeActive="{Binding ElementName=ModeToggleButton, Path=IsChecked}"
ContentRequested="OnContentRequested"
/>
</Grid>
The panel uses a unified event-driven architecture for all content requests:
// Handle all content requests - both initial and split operations
private void OnContentRequested(object sender, ContentRequestedEventArgs e)
{
// Handle initial panel content
if (e.RequestType == ContentRequestType.InitialPane)
{
e.RequestedContent = new Border
{
Background = Brushes.LightBlue,
Child = new TextBlock
{
Text = $"Initial Panel {DateTime.Now:HH:mm:ss}",
HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center
}
};
e.Handled = true;
}
// Handle split panel content
else if (e.RequestType == ContentRequestType.SplitPane)
{
e.RequestedContent = new Border
{
Background = Brushes.LightGreen,
Child = new TextBlock
{
Text = $"Split Panel {DateTime.Now:HH:mm:ss}\nDirection: {(e.IsVerticalSplit == true ? "Vertical" : "Horizontal")}",
HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center
}
};
e.Handled = true;
}
}
Split the selected panel programmatically:
// Split vertically at 50%
flexiPanel.SplitSelectedVertically(0.5);
// Split horizontally with custom content
var customContent = new TextBlock { Text = "New Panel" };
flexiPanel.SplitSelectedHorizontally(0.3, customContent);
Customize behavior through comprehensive events:
// Validate panel closing
flexiPanel.PaneClosing += (s, e) => {
if (HasUnsavedChanges(e.Pane)) {
e.Cancel = MessageBox.Show("Discard changes?", "Confirm",
MessageBoxButton.YesNo) == MessageBoxResult.No;
}
};
// Handle last panel scenario
flexiPanel.LastPaneClosing += (s, e) => {
e.Cancel = MessageBox.Show("Close last panel?", "Confirm",
MessageBoxButton.YesNo) == MessageBoxResult.No;
};
// Track split mode changes
flexiPanel.SplitModeChanged += (s, e) => {
statusLabel.Text = $"Split Mode: {(e.IsActive ? "ON" : "OFF")}";
};
The library uses a binary tree structure for managing panels:
FlexiPanel
└── RootContent
├── FlexiPaneItem (leaf node)
└── FlexiPaneContainer (branch node)
├── FirstChild
└── SecondChild
Enable interactive split mode with visual overlays and mouse interaction:
<ToggleButton x:Name="SplitToggle" Content="Toggle Split Mode" />
<flexiPane:FlexiPanel IsSplitModeActive="{Binding ElementName=SplitToggle, Path=IsChecked}" />
Or programmatically:
flexiPanel.IsSplitModeActive = true;
// Interactive split overlays and close buttons are automatically shown
When split mode is active:
The library automatically handles different content types:
private void OnContentRequested(object sender, ContentRequestedEventArgs e)
{
// Return any UIElement - FlexiPanel automatically wraps it for splitting
e.RequestedContent = new UserControl(); // Gets wrapped in FlexiPaneItem
e.RequestedContent = new TextBlock(); // Gets wrapped in FlexiPaneItem
e.RequestedContent = new FlexiPaneItem(); // Used directly
}
The panel intelligently manages complex layouts:
The library automatically tracks the selected panel:
// Get the currently selected panel
var selected = flexiPanel.SelectedItem;
// Set selection programmatically
somePane.IsSelected = true;
// Track selection changes
flexiPanel.SelectionChanged += (s, e) => {
Console.WriteLine($"Selected: {e.NewSelection?.Title}");
};
For the absolute simplest setup:
<!-- This works out of the box! -->
<flexiPane:FlexiPanel />
The panel will:
IsSplitModeActive is set to trueCheck out the FlexiPane.Samples.DefaultApp project for complete working examples:
To run the demo:
git clone https://github.com/iyulab/FlexiPane.WPF.git
cd FlexiPane.WPF
dotnet run --project src/FlexiPane.Samples.DefaultApp/
The simple demo shows the minimum code required to get a fully functional split panel system working!
The demo applications showcase advanced interactive features:
Contributions are welcome! Please feel free to:
Please read our contributing guidelines before submitting PRs.
This project is licensed under the MIT License - see the LICENSE file for details.
Developed by iyulab
Built with modern WPF best practices and inspired by proven splitting mechanisms from advanced development environments.
✅ Production Ready - The library is stable and ready for production use. Semantic versioning is followed for all releases.