Viewbox makes WindowsFormsHost disappear in WPF

2019-07-10 02:19发布

问题:

I have a WPF project where I maintain video ratio, by placing video control inside a ViewBox. The video control is a WinForms object wrapped inside a WindowsFormsHost. I also added a gridSplitter to resize the ViewBox. It all worked great, until I noticed a strange bug. When I would use the gridSplitter control to minimize the ViewBox close to zero, the video ratio would get screwed up after expanding it again. And when I used gridSplitter to contract the ViewBox all the way down to 0, the WindowsFormHost would completely disappear after expanding (it's still there, but it's ActualWidth and ActualHeight are now 0).

Removing the ViewBox control, and just using WindowsFormsHost works fine, but I need the ViewBox to control the aspect ratio. If I can't find a solution, I will have to control the ratio myself as a workaround.

I figured I must be doing something wrong, so I wrote a quick test program that reproduces the problem. I will post a link to the complete program below (it's in C#, VS2008).

In the test program I create a grid with two columns with a gridsplitter that lets you resize them. I then place a ViewBox in the left control and place a WindowsFormsHost inside it. I then host a red _winFormsButton inside the WindowsFormsHost.

The button scales fine, until you completely contract the left column and then expand it again. The button is gone. How do I prevent that from happening, so the button continues to scale after contracting and expanding left column? Thanks.

XAML:

<Window x:Class="DisappearingHost.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300">
    <Grid>        
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="0.5*" />
            <ColumnDefinition Width="0.5*" />
        </Grid.ColumnDefinitions>
        <GridSplitter Grid.Column="1" HorizontalAlignment="Left" Name="gridSplitter1" Width="10" VerticalContentAlignment="Center" />        
        <Viewbox>
            <WindowsFormsHost Name="windowsFormsHost1" VerticalAlignment="Center" HorizontalAlignment="Center" />
        </Viewbox>
    </Grid>
</Window>

Code Behind:

public partial class Window1 : Window
    {
        System.Windows.Forms.Button _winFormsButton = new System.Windows.Forms.Button();

        public Window1()
        {
            InitializeComponent();

            _winFormsButton.Text = "I disappear!";
            _winFormsButton.Size = new System.Drawing.Size(50, 50);
            _winFormsButton.BackColor = System.Drawing.Color.Red;

            windowsFormsHost1.Child = _winFormsButton;
        }
    }

Sample code output:

Link to test project code (VS2008): code

回答1:

Place your grid splitter in Column zero, so you won't have WPF layout fight. Here is the modified code (notice Grid Splitter column, horiz alignment, and view box margin):

<GridSplitter Grid.Column="0" HorizontalAlignment="Right" Name="gridSplitter1" Width="10" VerticalContentAlignment="Center" />
        <Viewbox Margin="10">
            <WindowsFormsHost Name="windowsFormsHost1" VerticalAlignment="Center" HorizontalAlignment="Center" />
        </Viewbox>

You can make the ViewBox margin just on the right to make it look better



回答2:

I ended up getting rid of the Viewbox, and controlling WidowsFormHost dimensions myself.