[英]How to force a certain UserControl design
我正在編寫一個基本的UserControl,它將被一堆其他UserControl繼承。 我需要為所有這些后代控件強制執行某種設計(例如,幾個按鈕必須在頂部以及一個或兩個標簽)。
子孫UserControl區域的其余部分可以自由放置任何內容。
最初,我認為我可以將面板放到基本UserControl上,設置Dock = Fill,后代控件的設計者將被迫將所有UI添加到該面板中。 然后,我可以將面板調整為適合我的內容的大小。
事實並非如此-將控件(例如GridView)放到后代UserControl上時,它將它添加到后代用戶控件的.Controls集合中,而不是我添加的Panel中。
有沒有辦法從基本用戶控件中強制某種布局?
簡短的答案是“是”。但是,要使這種行為深入研究編寫自己的設計器的丑陋世界,您必須將其與每個控件相關聯,這需要將特殊位置繼承到內容面板中。
以下鏈接應該是一個很好的起點,因為它概述了需要完成的工作並提供了示例代碼。
http://support.microsoft.com/?id=813808
被警告,但是,這不是一件容易的事。 並且有很多代碼(30多個文件)可供篩選,以了解如何實現設計器。 自從我嘗試過大約兩年了。
另一方面,您是否考慮過將設計更改為具有一個帶有標簽和按鈕的單個父控件,並使用適當的子控件填充內容區域? 也許甚至讓您的孩子對內容區域進行控制都實現了一個特定的接口來保證合同,以便家長可以與他們進行交互而不必知道特定的類名?
AngryHacker-
我以為這很容易,然后發現自己踏上了進入WinForm設計時領域的有趣旅程。 這絕對不像在VB6中那么容易:-)。
無論如何,經過一番研究,我發現了許多對名為EnableDesignMode()的方法的引用。 但是,這不能從WinForm組件直接訪問。 這必須從ParentControlDesigner子類的類中調用,該類通過Designer屬性注入到UserControl中。 在這個項目中,我調用了子類ButtonBarDesigner ,並且重寫了Initialize()方法,該方法使我可以告訴設計器ButtonBar組件具有子組件fillPanel ,可以通過公共屬性“ FillPanel”對其進行訪問。
在這一點上,它似乎正在工作。 我設法將一個控件放到ButtonBar上,它出現在填充面板中。 但是,如果您保存了表單,然后重新加載了表單,事實證明該控件已實例化,但未放置在ButtonBar控件中。 似乎有一點偷偷摸摸的地方, EnableDesignMode()的文檔方便地省略了這一點。 您需要在FillPanel屬性上具有DesignerSerializationVisibility屬性。 添加此屬性即可完成這項工作。
您需要在項目中引用System.Design才能使設計時工作正常。
以下代碼用於假定的基類ButtonBar:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.Windows.Forms.Design;
using System.Threading;
namespace ForceUserControl
{
[Designer(typeof(ButtonBarDesigner))]
public partial class ButtonBar : UserControl
{
public ButtonBar()
{
InitializeComponent();
}
/// <summary>
/// Returns inner panel.
/// </summary>
/// <remarks>Should allow persistence.</remarks>
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public Panel FillPanel
{
get { return fillPanel; }
}
}
private class ButtonBarDesigner : ParentControlDesigner
{
public override void Initialize(IComponent component)
{
base.Initialize(component);
Panel fillPanel = ((ButtonBar)component).FillPanel;
// The name should be the same as the public property used to return the inner panel control.
base.EnableDesignMode(fillPanel, "FillPanel");
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.