Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
136 changes: 84 additions & 52 deletions wpf/Tabbed-Window/data-binding.md
Original file line number Diff line number Diff line change
@@ -1,67 +1,69 @@
---
layout: post
title: Data Binding in WPF Tabbed Window | Syncfusion
description: Bind tabs to a collection using the ItemsSource property to support MVVM‑based tabbed window scenarios.
description: Learn how to bind tabs to a collection in a WPF tabbed window by using the ItemsSource property and templates for tab headers and content.
platform: wpf
control: TabbedWindow
documentation: ug
---

# WPF Tabbed Window - Data Binding
# Data Binding in WPF Tabbed Window

## Overview
This section explains how to bind tabs to a collection in a WPF tabbed window by using the `ItemsSource` property of [SfTabControl](https://help.syncfusion.com/cr/wpf/Syncfusion.Windows.Controls.SfTabControl.html) and defining templates for tab headers and content.

The Tabbed Window provides full MVVM support through data binding. You can bind tabs to a collection using the `ItemsSource` property, enabling data-driven tab creation and dynamic content updates.
## Adding Tab Items using Data Binding

## ItemsSource Binding

Bind the `ItemsSource` property to a collection in your ViewModel. Each item automatically generates a corresponding tab:
You can bind the `ItemsSource` property of [SfTabControl](https://help.syncfusion.com/cr/wpf/Syncfusion.Windows.Controls.SfTabControl.html) to a collection in the ViewModel to generate tabs automatically. Each item in the bound collection creates a corresponding tab.

{% tabs %}

{% highlight C# %}

// TabModel.cs
public class TabModel {
public string Header { get; set; }
public string Content { get; set; }
public class TabModel
{
public string Header { get; set; }
public string Content { get; set; }
}

// MainViewModel.cs
public class MainViewModel : NotificationObject {
public ObservableCollection<TabModel> TabItems { get; } = new ObservableCollection<TabModel>();

public MainViewModel() {
TabItems.Add(new TabModel { Header = "Tab 1", Content = "First tab content" });
TabItems.Add(new TabModel { Header = "Tab 2", Content = "Second tab content" });
}
public class MainViewModel : NotificationObject
{
public ObservableCollection<TabModel> TabItems { get; } = new ObservableCollection<TabModel>();

public MainViewModel()
{
TabItems.Add(new TabModel { Header = "Tab 1", Content = "First tab content" });
TabItems.Add(new TabModel { Header = "Tab 2", Content = "Second tab content" });
}
}

{% endhighlight %}

{% highlight XAML %}

<Window.DataContext>
<local:MainViewModel />
<local:MainViewModel />
</Window.DataContext>

<syncfusion:SfTabControl ItemsSource="{Binding TabItems}" x:Name="MainTabControl">
<!-- Header template via ItemContainerStyle -->
<syncfusion:SfTabControl.ItemContainerStyle>
<Style TargetType="syncfusion:SfTabItem">
<Setter Property="HeaderTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock Text="{Binding Header}" />
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</syncfusion:SfTabControl.ItemContainerStyle>

<!-- Content template -->
<syncfusion:SfTabControl.ContentTemplate>
<DataTemplate>
<TextBlock Text="{Binding Content}" />
</DataTemplate>
</syncfusion:SfTabControl.ContentTemplate>
<syncfusion:SfTabControl.ItemContainerStyle>
<Style TargetType="syncfusion:SfTabItem">
<Setter Property="HeaderTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock Text="{Binding Header}" />
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</syncfusion:SfTabControl.ItemContainerStyle>

<syncfusion:SfTabControl.ContentTemplate>
<DataTemplate>
<TextBlock Text="{Binding Content}" />
</DataTemplate>
</syncfusion:SfTabControl.ContentTemplate>
</syncfusion:SfTabControl>

{% endhighlight %}
Expand All @@ -70,30 +72,60 @@ public class MainViewModel : NotificationObject {

![WPF TabbedWindow](data-binding_images/wpf_tabbedwindow.png)

## Customization of TabItems
## Tab Item Header

You can define the tab item header by using the `HeaderTemplate` property in `ItemContainerStyle` or by using the `ItemTemplate` property. This keeps the header content bound to the underlying data object for each generated tab.

{% tabs %}

{% highlight XAML %}

<Window.DataContext>
<local:MainViewModel />
</Window.DataContext>

<syncfusion:SfTabControl ItemsSource="{Binding TabItems}" x:Name="MainTabControl">
<syncfusion:SfTabControl.ItemContainerStyle>
<Style TargetType="syncfusion:SfTabItem">
<Setter Property="HeaderTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock Text="{Binding Header}" />
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</syncfusion:SfTabControl.ItemContainerStyle>
</syncfusion:SfTabControl>

{% endhighlight %}

{% endtabs %}

Use the ItemTemplate to control the visual presentation of each tab, defining separate templates for the tab header and tab content to enable flexible and reusable UI composition.
![WPF TabbedWindow](data-binding_images/wpf_tabbedwindow_header.png)

## Tab Item Content

You can define the tab item content by using the `ContentTemplate` property of [SfTabControl](https://help.syncfusion.com/cr/wpf/Syncfusion.Windows.Controls.SfTabControl.html). This allows the content area of each generated tab to display bound values from the data object.

{% tabs %}

{% highlight XAML %}

<DataTemplate x:Key="TabHeaderTemplate">
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
<Image Source="/Images/doc.png" Width="16" Height="16"/>
<TextBlock Text="{Binding Title}" Margin="6,0,0,0"/>
</StackPanel>
</DataTemplate>
<Window.DataContext>
<local:MainViewModel />
</Window.DataContext>

<DataTemplate x:Key="TabContentTemplate">
<ContentPresenter Content="{Binding Content}" />
</DataTemplate>
<syncfusion:SfTabControl ItemsSource="{Binding TabItems}" x:Name="MainTabControl">
<syncfusion:SfTabControl.ContentTemplate>
<DataTemplate>
<TextBlock Text="{Binding Content}" />
</DataTemplate>
</syncfusion:SfTabControl.ContentTemplate>
</syncfusion:SfTabControl>

<syncfusion:SfTabControl ItemsSource="{Binding OpenTabs}"
ItemTemplate="{StaticResource TabHeaderTemplate}"
ContentTemplate="{StaticResource TabContentTemplate}" />
{% endhighlight %}

{% endtabs %}

![WPF TabbedWindow customization](data-binding_images/wpf_customization.png)
![WPF TabbedWindow](data-binding_images/wpf_tabbedwindow_contenttemplate.png)
Binary file not shown.
Binary file modified wpf/Tabbed-Window/data-binding_images/wpf_tabbedwindow.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
66 changes: 18 additions & 48 deletions wpf/Tabbed-Window/merge-tabs.md
Original file line number Diff line number Diff line change
@@ -1,34 +1,25 @@
---
layout: post
title: Merge Tabs Between Windows in WPF Tabbed Window | Syncfusion
description: Move tabs between multiple tabbed windows and manage merge operations with validation to ensure correct behavior.
description: Learn how to detach tabs into floating windows and validate tab movement between tabbed windows by using tear-off support and the PreviewTabMerge event.
platform: wpf
control: TabbedWindow
documentation: ug
---

# WPF Tabbed Window - Merge Tabs Between Windows
# Merge Tabs Between Windows in WPF Tabbed Window

## Overview

The Tabbed Window supports merging tabs between multiple windows through drag-and-drop operations. This enables users to reorganize content across multiple windows and create flexible workspace configurations.
This section explains how to move tabs between tabbed windows and provides an overview of the supported tear-off and merge validation features.

## Tear-Off Windows

The Tabbed Window supports tear-off functionality that allows users to detach tabs and create independent floating windows. These floating windows operate as separate TabbedWindow instances and can be reattached to the main window later.

### Creating Floating Windows

To tear off a tab and create a floating window:

1. Drag a tab outside the boundary of the tab control
2. A new floating window is automatically created
3. The tab is now contained in the new floating window
4. The floating window can be a new tabbed window
The tabbed window interface supports tear-off functionality that allows tabs to be detached from an [SfTabControl](https://help.syncfusion.com/cr/wpf/Syncfusion.Windows.Controls.SfTabControl.html) and displayed in independent floating windows. These floating windows can later be merged back into another tabbed window.

### Enable Tear-Off

Ensure `AllowDragDrop` is enabled, which is the prerequisite for tear-off functionality:
You can use the [AllowDragDrop](https://help.syncfusion.com/cr/wpf/Syncfusion.Windows.Controls.SfTabControl.html#Syncfusion_Windows_Controls_SfTabControl_AllowDragDrop) property to enable tear-off support in [SfTabControl](https://help.syncfusion.com/cr/wpf/Syncfusion.Windows.Controls.SfTabControl.html). When drag-and-drop is enabled, a tab can be dragged outside the tab control boundary to create a floating window. The detached tab is moved into the new window automatically, and it can be reattached later by dragging it back into the tab area of another tabbed window. If a floating window becomes empty after a tab is moved out, it is closed automatically.

The floating window created through tear-off behaves like a regular tabbed window. It can be moved, resized, and minimized, and it supports the same tab features as the original window.

{% tabs %}

Expand All @@ -45,34 +36,15 @@ Ensure `AllowDragDrop` is enabled, which is the prerequisite for tear-off functi
</syncfusion:SfTabControl>
</syncfusion:SfChromeslessWindow>


{% endhighlight %}

{% endtabs %}

![WPF TabbedWindow Tear-Off](merge-tabs_images/tear-off-tabbedwindow.gif)

### Reattaching Floating Tabs

To reattach a tab from a floating window back to the main window:

1. Drag the tab from the floating window
2. Drop it inside the main window's tab area
3. The tab is automatically integrated back into the main window
4. The floating window is closed if it becomes empty

### Floating Window Behavior

Each floating window created by tearing off a tab:
- Is a fully functional TabbedWindow instance
- Inherits SfChromelessWindow properties
- Can be resized, moved, and minimized
- Supports the same tab features as the main window (drag-drop, new tabs, close buttons)
- Can have additional tabs dragged into it

## Control Tab Movement with PreviewTabMerge

The `PreviewTabMerge` event fires before a tab is moved between windows, allowing you to validate or cancel the merge operation:
You can use the [PreviewTabMerge](https://help.syncfusion.com/cr/wpf/Syncfusion.Windows.Controls.SfTabControl.html#Syncfusion_Windows_Controls_SfTabControl_PreviewTabMerge) event to validate or cancel a tab merge operation before a tab is moved between tabbed windows. This event also allows you to modify the item that will be inserted into the target [SfTabControl](https://help.syncfusion.com/cr/wpf/Syncfusion.Windows.Controls.SfTabControl.html).

{% tabs %}

Expand All @@ -94,7 +66,7 @@ private void OnPreviewTabMerge(object sender, TabMergePreviewEventArgs e)
var draggedItem = e.DraggedItem;
var sourceControl = e.SourceControl;
var targetControl = e.TargetControl;

// Validate the merge
if (draggedItem is Document doc && doc.IsLocked)
{
Expand All @@ -103,18 +75,18 @@ private void OnPreviewTabMerge(object sender, TabMergePreviewEventArgs e)
MessageBox.Show("Cannot move locked documents");
return;
}

// Optional: Transform the item before merge
if (draggedItem is Document docItem)
{
e.ResultingItem = new Document
{
e.ResultingItem = new Document
{
Title = docItem.Title,
Content = docItem.Content,
CreatedAt = DateTime.Now
};
}

// Allow the merge
e.Allow = true;
}
Expand All @@ -129,10 +101,8 @@ private void OnPreviewTabMerge(object sender, TabMergePreviewEventArgs e)

| Property | Type | Description |
|----------|------|-------------|
| `DraggedItem` | object | The item being dragged |
| `SourceControl` | SfTabControl | The control where drag originated |
| `TargetControl` | SfTabControl | The control receiving the item |
| `Allow` | bool | Set to false to cancel merge (default: true) |
| `ResultingItem` | object | The item to be inserted (default: DraggedItem) |


| `DraggedItem` | object | The item being dragged. |
| `SourceControl` | SfTabControl | The tab control where the drag operation started. |
| `TargetControl` | SfTabControl | The tab control that receives the dragged item. |
| `Allow` | bool | Specifies whether the merge operation is allowed. Set this to `false` to cancel the merge. |
| `ResultingItem` | object | The item to be inserted into the target control. By default, this is the same as `DraggedItem`. |