如何在MDI中正确显示Windows窗体应用程序中的子边栏和子窗体?

时间:2019-01-22 10:51:03

标签: c# winforms layout mdi

我正在尝试设计一个具有一个子边栏窗体和多个子窗体的MDI。

当单击“排列”按钮时,我试图使布局显示在以下屏幕截图中(侧边栏和最顶部打开的子项并排显示):

enter image description here

初始化侧边栏

sideBarForm = new Form();
sideBarForm.MdiParent = this;    
sideBarForm.Show();
sideBarForm.Dock = DockStyle.Right;
sideBarForm.FormBorderStyle = FormBorderStyle.FixedToolWindow;
sideBarForm.Name = "sideBarForm";

添加新孩子

Form childForm = new Form();
childForm.MdiParent = this;
childForm.Show();

安排布局

 private void Arrange_Click(object sender, EventArgs e)
 {
    foreach (Form child in MdiChildren)
    {
        if (child.Name != sideBarForm.Name)
        {
            child.WindowState = FormWindowState.Normal;
            child.Width = this.ClientRectangle.Width - sideBarForm.Width - 50;
            child.Height = this.ClientRectangle.Height - 150;
        }
    }
 }

为了使两种形式并排正确,它需要“玩”数字。对于宽度,我删除了50px,对于高度为150px。

两种表格并排的正确方法是什么?

注意:MDI可以包含多个打开的表单,因此例如,我不能使用SplitContainer或TableLayoutPanel。

4 个答案:

答案 0 :(得分:1)

Mdi窗口尊重停靠的内容,并将剩余区域用于mdi子窗口。

因此,对于侧边栏,请勿将其添加为mdi窗口,而应将其添加为停靠窗口。对于其余窗口,将它们添加为mdi子窗口:

private void Form1_Load(object sender, EventArgs e)
{
    IsMdiContainer = true;
    var sideBar = new Form();
    sideBar.Text = "SideBar";
    sideBar.TopLevel = false;
    sideBar.FormBorderStyle = FormBorderStyle.FixedToolWindow;
    sideBar.Dock = DockStyle.Right;
    this.Controls.Add(sideBar);

    var f1= new Form();
    f1.Text = "Mdi Child 1";
    f1.MdiParent = this;

    var f2 = new Form();
    f2.Text = "Mdi Child 2";
    f2.MdiParent = this;

    sideBar.Show();
    f1.Show();
    f2.Show();
}

答案 1 :(得分:0)

创建一个mdi表单并向其中添加一个面板,然后将面板的停靠属性设置为right。就像下面的屏幕截图一样:

enter image description here

使用

LayoutMdi(MdiLayout.TileVertical);

事件代码类似于下面的屏幕截图:

enter image description here

在您的MDI表单上。它将在MDI窗口中并排排列所有打开的表单。最终的屏幕截图如下:

enter image description here

答案 2 :(得分:0)

您可以使用两个面板(一个DockStyle.Right和另一个DockStyle.Fill),并将子窗体添加到面板,例如:

@Value("${sftp.host}")
private String host;

@Value("${sftp.port:22}")
private int port;

@Value("${sftp.user}")
private String user;

@Value("${sftp.privateKey:#{null}}")
private Resource privateKey;

@Value("${sftp.privateKeyPassphrase:}")
private String privateKeyPassphrase;

@Value("${sftp.password:#{null}}")
private String password;

private final FileService fileService;

@Autowired
public SftpConfig(FileService fileService) {
    this.fileService = fileService;
}

@Bean
public SessionFactory<LsEntry> sftpSessionFactory() {
    DefaultSftpSessionFactory factory = new DefaultSftpSessionFactory(true);
    factory.setHost(host);
    factory.setPort(port);
    factory.setUser(user);
    if (privateKey != null) {
        factory.setPrivateKey(privateKey);
        factory.setPrivateKeyPassphrase(privateKeyPassphrase);
    } else {
        factory.setPassword(password);
    }
    factory.setAllowUnknownKeys(true);
    return new CachingSessionFactory<LsEntry>(factory);
}

@Bean
public IntegrationFlow sftpOutboundFlow() {
    return IntegrationFlows.from("toSftpChannel")
            .handle(Sftp.outboundAdapter(this.sftpSessionFactory(), FileExistsMode.FAIL)
                            .remoteDirectoryExpression("headers['path']")
                            .useTemporaryFileName(false)
                            .autoCreateDirectory(true)
                            .fileNameGenerator(message -> (String) message.getHeaders().get("fileName"))
                    , c -> c.advice(expressionAdvice())
            ).get();
}

@Bean
public Advice expressionAdvice() {
    ExpressionEvaluatingRequestHandlerAdvice advice = new ExpressionEvaluatingRequestHandlerAdvice();
    advice.setSuccessChannelName("integrationFlow.input");
    advice.setOnSuccessExpressionString("payload");
    advice.setFailureChannelName("integrationFlow.input");
    advice.setOnFailureExpressionString("payload");
    advice.setTrapException(true);
    return advice;
}

@Bean
public IntegrationFlow integrationFlow() {
    return f -> f.handle((MessageHandler) fileService::OnFilesUpload);
}

@MessagingGateway
public interface UploadGateway {

    @Gateway(requestChannel = "toSftpChannel")
    void upload(@Payload File file, @Header("fileName") String fileName, @Header("path") String path,
                @Header("parentId") Long parentId);

}

致谢!

答案 3 :(得分:0)

鉴于您显示的布局,在其“调整大小”事件中将 SideBarForm 宽度重置为所需的尺寸应该足够了。

首先将SideBarForm表单添加到MDIChildren集合中,将其停靠在所需的一侧,然后 SendToBack() 。这将在对接堆栈中为工具栏赋予更高的优先级。

另一个MDI子窗体将停靠以填充剩余空间。
调整MDIParent的大小或使其最大化时,将保留该处置。

MDIParent 表单中:

private int sideBarSize = 150;

private void MDIParent_Load(object sender, EventArgs e)
{
    this.MinimumSize = new Size(sideBarSize * 2, sideBarSize * 2);

    SideBarForm sideBarForm = new SideBarForm(sideBarSize);
    ChildForm childForm = new ChildForm();

    sideBarForm.MdiParent = this;
    sideBarForm.FormBorderStyle = FormBorderStyle.FixedToolWindow;
    sideBarForm.Size = new Size(sideBarSize, this.ClientRectangle.Height);
    sideBarForm.Dock = DockStyle.Right;
    sideBarForm.SendToBack();
    sideBarForm.Show();

    childForm.MdiParent = this;
    childForm.BringToFront();
    childForm.Dock = DockStyle.Fill;
    childForm.Show();
}

SideBarForm中:

private int myWidth = 0;

public SideBarForm() : this(150) { }
public SideBarForm(int MySize) 
{
    InitializeComponent();
    this.myWidth = MySize;
    this.Width = MySize;
}

private void SideBarForm_Resize(object sender, EventArgs e)
{
    this.Width = myWidth;
}