Search code examples
c#wpfwinformswinforms-interop

Winform control spills outside of the WPF tab


If a WPF TabItem is not large enough to host a Winform control, then the Winform control will spill out of the TabItem, resulted in some other spaces in the TabControl being hidden, as shown below, the Winform button is spilling out of the tab:

enter image description here

How to make sure that the winform control is always contained inside the tab?

Here's the full source code:

MainWindow.xaml

<Window
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:DockingManagerScrollItem"
        x:Class="DockingManagerScrollItem.MainWindow"
        mc:Ignorable="d"
        Title="MainWindow" Height="500" Width="500">
    <Grid>


        <TabControl Width="450" HorizontalAlignment="Left">
            <TabItem Header="First Tab">
                <local:SingleTab/>
            </TabItem>
        </TabControl>


    </Grid>
</Window>

Winform control ( SimpleThing.designer.cs)

partial class SimpleThing
{
    /// <summary> 
    /// Required designer variable.
    /// </summary>
    private System.ComponentModel.IContainer components = null;

    /// <summary> 
    /// Clean up any resources being used.
    /// </summary>
    /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
    protected override void Dispose(bool disposing)
    {
        if (disposing && (components != null))
        {
            components.Dispose();
        }
        base.Dispose(disposing);
    }

    #region Component Designer generated code

    /// <summary> 
    /// Required method for Designer support - do not modify 
    /// the contents of this method with the code editor.
    /// </summary>
    private void InitializeComponent()
    {
        this.button1 = new System.Windows.Forms.Button();
        this.SuspendLayout();
        // 
        // button1
        // 
        this.button1.Dock = System.Windows.Forms.DockStyle.Fill;
        this.button1.Location = new System.Drawing.Point(0, 0);
        this.button1.Name = "button1";
        this.button1.Size = new System.Drawing.Size(623, 429);
        this.button1.TabIndex = 0;
        this.button1.Text = "button1";
        this.button1.UseVisualStyleBackColor = true;
        // 
        // SimpleThing
        // 
        this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
        this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
        this.Controls.Add(this.button1);
        this.Name = "SimpleThing";
        this.Size = new System.Drawing.Size(623, 429);
        this.ResumeLayout(false);

    }

    #endregion

    private System.Windows.Forms.Button button1;
}

WinformWrapper

public class WinformWrapper : WindowsFormsHost
{

private SimpleThing _mapControl;
public WinformWrapper()
{

    _mapControl = new SimpleThing();
    Child = _mapControl;


}

}

SingleTab.xaml

<UserControl x:Class="DockingManagerScrollItem.SingleTab"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:DockingManagerScrollItem"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto">
        <Grid ScrollViewer.CanContentScroll="True" ShowGridLines="True">
            <Grid.RowDefinitions>
                <RowDefinition Height="100"/>
                <RowDefinition Height="200" />
            </Grid.RowDefinitions>

            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="100" />
                <ColumnDefinition Width="600" />
                <ColumnDefinition Width="*" />

            </Grid.ColumnDefinitions>

            <TextBlock Grid.Row="0" Grid.Column="2" Text="hello" />
            <local:WinformWrapper Grid.Row="0" Grid.Column="1" Grid.RowSpan="2" Margin="30" />
        </Grid>
    </ScrollViewer>
</UserControl>

Solution

  • Set the size of the WindowsFormsHost to the size of the hosted child control:

    public class WinformWrapper : WindowsFormsHost
    {
        private SimpleThing _mapControl;
        public WinformWrapper()
        {
            _mapControl = new SimpleThing();
            Child = _mapControl;
            Width = _mapControl.Width;
            Height = _mapControl.Height;
        }
    }
    

    Or see this:

    ScrollViewer is not working in WPF WindowsFormHost