c# - Winforms/WPF 互操作 - 调整嵌套用户控件的大小

标签 c# wpf winforms-interop

我有一个 winforms 用户控件,它包含一个元素主机,它本身包含一个包含文本框的 wpf 用户控件。

我似乎无法正常调整最里面的文本框的大小。理想情况下,它会调整大小以填充 elementhost,并且它本身会调整大小以在调整大小时填充 winforms 用户控件。

winforms usercontrol 的构造函数代码如下

public partial class TextBox : UserControl, ITextBox
{
    private System.Windows.Forms.Integration.ElementHost _textBoxHost;
    private TextBoxExViewModel _viewModel;
    private TextBoxEx _textBoxEx;

    public TextBox()
    {
        InitializeComponent();

        this._textBoxHost = new System.Windows.Forms.Integration.ElementHost();           
        this._textBoxEx = new IfxNetControls.TextBoxEx();
        this._viewModel = new TextBoxExViewModel();

        _textBoxEx.DataContext = _viewModel;

        this.SuspendLayout();

        // set up wpf host elementHost1             
        this._textBoxHost.Dock = System.Windows.Forms.DockStyle.Fill;
        this._textBoxHost.Location = new System.Drawing.Point(0, 0);
        this._textBoxHost.Name = "textBoxHost";
        this._textBoxHost.Size = new System.Drawing.Size(340, 245);
        this._textBoxHost.TabIndex = 0;
        this._textBoxHost.Text = "textBoxHost";
        this._textBoxHost.AutoSize = false;
        this._textBoxHost.ChildChanged += new System.EventHandler<System.Windows.Forms.Integration.ChildChangedEventArgs>(this.ChildChanged);
        this._textBoxHost.Child = this._textBoxEx;
        //this._elementHost1.Child = this._wpfTextBox;

        // set up usercontrol textbbox 
        this.Controls.Add(this._textBoxHost);
        this.Name = "TextBox";
        this.Size = new System.Drawing.Size(340, 245);
        this.AutoSize = false;

        //
        this.ResumeLayout(false);
    }

    ...

注意 Dock 属性设置为 Fill

我还尝试了 Winforms 用户控件中的调整大小处理程序

private void TextBox_Resize(object s, EventArgs e)
{                
    this._textBoxEx.Width = this._textBoxHost.Width;
    this._textBoxEx.Height = this._textBoxHost.Height; 
}

因为当我用高度和宽度进行追踪时,wpf 文本框总是更小

WinformsUserControl: 208,35
ElementHost: 208,35
WpfUsercontrol: 181.527272727273,30.5454545454545

这似乎在使用时反射(reflect)出来(见下面的 img 3)——尽管我确实想知道所有 3 个控件的测量单位是否相同。

wpf 用户控件 xaml 如下所示

<UserControl x:Class="IfxNetControls.TextBoxEx"
         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:..."             
         mc:Ignorable="d" 
         d:DesignHeight="450" d:DesignWidth="800"
         HorizontalAlignment="Stretch"
         VerticalAlignment="Stretch"
         HorizontalContentAlignment="Stretch"
         VerticalContentAlignment="Stretch"
         Height="Auto"
         Width="Auto"
         Margin="0"
         Padding="0"
         >
...

文本框 xaml 的高度和宽度设置为“自动”。我还尝试将水平/垂直对齐方式和 ContentAlignment 设置为拉伸(stretch)。

显示时,它最初看起来像这样。 (我放置了 2 个相同尺寸以显示变化)

enter image description here

最初最上面的那个有焦点,但如果我将焦点从它移开,它会调整到看起来像文本的大小(即使我已明确将 Autosize 设置为 false)。

enter image description here

如果我弄乱了背景颜色,它看起来像这样,它似乎揭示了文本框与其容器的不同大小,底部和左侧有边距

enter image description here

理想情况下,所有控件的大小都相同(并且背景颜色相同!)。

我对 wpf 不是很熟悉,所以我想知道是否有人可以指出我的错误。

EDIT-1:所以我仍在努力弄清楚问题到底是什么!

如果我更新 winforms 用户控件的背景颜色而不更改 XAML 用户控件或文本框的背景,当文本框没有有焦点时看起来像这样

enter image description here

但是,当它获得焦点时,wpfusercontrol/textbox 看起来会扩展以填充 winforms usercontrol 容器 - 因此:

enter image description here

然后在失去焦点时,它会返回到之前的大小,再次显示 winforms 用户控件的背景。

我不太明白,因为当我跟踪elementhost的宽度和高度时,它的大小已经和winforms usercontrol一样了。我已经为 wpf 用户控件提供了它自己的背景颜色,但我从来没有看到它表明文本框实际上正确地填充了 wpf 用户控件。似乎 wpf usercontrol/textbox 在我不期望的点调整大小。

这是预期的行为吗?

再次感谢。

最佳答案

在 WPF 中,您通常使用 StylesTemplatesCustom Controls。这些有很多教程,我建议看看这些。 UserControls 没有这些灵活,通常用于创建不需要那么灵活的大型 UI。例如创建一个表单。

Ideally, all controls would be the same size (and the same back colour!).

在这种情况下,我建议您使用样式

此处解释了 Auto* 的工作原理以及如何使用 Style

<Window x:Class="WpfApp1.MainWindow"
    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:WpfApp1"
    mc:Ignorable="d"
    Title="MainWindow" Height="450" Width="800">
<Window.Resources>
    <Style TargetType="{x:Type TextBox}"> <!-- Style for all Textboxes on this window -->
        <Setter Property="TextAlignment" Value="Left"/>
        <Setter Property="Width" Value="180"/>
        <Setter Property="Margin" Value="5"/> <!-- the same as 5,5,5,5  left,top,right,bottom  -->
        <Setter Property="Background" Value="Blue"/>
    </Style>
</Window.Resources>
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition  Width="2*"/><!-- It's 2 times wider than the other colums with * -->
        <ColumnDefinition Width="Auto"/> <!-- the Column width is based on the widest control in this column -->
        <ColumnDefinition /><!-- you can also write Width="*" -->
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition/> <!-- you can also write Height="*" -->
        <RowDefinition Height="Auto"/> <!-- the Row's Height is based on the highest control in this row -->
        <RowDefinition Height="Auto"/> <!-- the Row's Height is based on the highest control in this row -->
        <RowDefinition Height="Auto"/> <!-- the Row's Height is based on the highest control in this row -->
        <RowDefinition Height="Auto"/> <!-- the Row's Height is based on the highest control in this row -->
        <RowDefinition/> <!-- you can also write Height="*" -->
    </Grid.RowDefinitions>
    <Grid Grid.Row="1" Grid.Column="1" Background="red"> <!-- Just to have a container. In your example this is the UserControl -->
        <TextBox />
    </Grid>
    <TextBox Grid.Row="2" Grid.Column="1"/>
    <TextBox Grid.Row="3" Grid.Column="1"/>

</Grid>

关于c# - Winforms/WPF 互操作 - 调整嵌套用户控件的大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52872412/

相关文章:

c# - 如何设置动态创建的表行的属性?

c# - NotifyOnPropertyChange实现

wpf - WPF 用户控件中的键盘输入不会发送到 WinForms 容器

c# - 覆盖标题栏按钮的工具提示文本(关闭、最大化、最小化、帮助)

c# - UWP 模态窗口

c# - 使用父模型值的子模型验证。流利的验证。 MVC4

c# - 安装 DotNET 4.5 时,SvcUtil/edb 不会生成 INotifyPropertyChange

c# - 可以在 View 中显示 RelayCommand 吗?

c# - 如何以编程方式在 Wpf 中的网格行内创建网格

c# - 为什么我的 WPF 托管 WinForm 是空白的?