以 TextBox 為例,點選控件右上角的三角符號,跳出來的 TextBox 工作,就是所謂的智能標籤
要建立智能標籤,要先引用 System.Design.dll
建立 ColorLabelActionList
using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Drawing;
namespace UCControlDesignerExample
{
/// <summary>
/// 自訂智能面板內容
/// </summary>
public class ColorLabelActionList : DesignerActionList
{
private ColorLabel colorLabel;
private DesignerActionUIService designerActionUISvc = null;
public ColorLabelActionList(IComponent component) : base(component)
{
this.colorLabel = component as ColorLabel;
// DesignerActionUIService 可以用來更新智能面板
this.designerActionUISvc = GetService(typeof(DesignerActionUIService)) as DesignerActionUIService;
}
/// <summary>
/// DesignerActionUIService 使用來更新智能面板,在本範例上 [鎖定顏色] 和 [反轉前後背景顏色] 會用上
/// </summary>
private void SmartTagPanelRefresh()
{
this.designerActionUISvc.Refresh(this.Component);
}
/// <summary>
/// 取得 ColorLabel Property
/// </summary>
/// <param name="propName">Property Name</param>
/// <returns>PropertyDescriptor</returns>
private PropertyDescriptor GetPropertyByName(String propName)
{
PropertyDescriptor prop = TypeDescriptor.GetProperties(colorLabel)[propName];
if (null == prop)
throw new ArgumentException($"ColorLabel 屬性:{propName} 沒有找到");
else
return prop;
}
#region DesignerActionPropertyItem:智能面版上的控件
public string Text
{
get
{
return colorLabel.Text;
}
set
{
GetPropertyByName(nameof(this.Text)).SetValue(colorLabel, value);
}
}
public Color BackColor
{
get
{
return colorLabel.BackColor;
}
set
{
GetPropertyByName(nameof(this.BackColor)).SetValue(colorLabel, value);
}
}
public Color ForeColor
{
get
{
return colorLabel.ForeColor;
}
set
{
GetPropertyByName(nameof(this.ForeColor)).SetValue(colorLabel, value);
}
}
public bool LockedColor
{
get
{
return colorLabel.LockedColor;
}
set
{
GetPropertyByName(nameof(this.LockedColor)).SetValue(colorLabel, value);
SmartTagPanelRefresh();
}
}
#endregion
#region DesignerActionMethodItem:智能面板上的方法
/// <summary>
/// 反轉前後背景顏色
/// </summary>
public void InvertColors()
{
Color currentBackColor = colorLabel.BackColor;
Color currentForeColor = colorLabel.ForeColor;
BackColor = currentForeColor;
ForeColor = currentBackColor;
SmartTagPanelRefresh();
}
#endregion
/// <summary>
/// 智能面板內容
/// </summary>
/// <returns></returns>
public override DesignerActionItemCollection GetSortedActionItems()
{
DesignerActionItemCollection items = new DesignerActionItemCollection();
// DesignerActionHeaderItem 使用
string Header_Appearance = "外觀";
string Header_Information = "控件資訊";
// 定義 Header
items.Add(new DesignerActionHeaderItem(Header_Appearance));
items.Add(new DesignerActionHeaderItem(Header_Information));
items.Add(new DesignerActionPropertyItem(
nameof(this.LockedColor), // 綁定的 Property
"鎖定顏色", // 文字說明
Header_Appearance, // Category:輸入 Header 名稱
"鎖定顏色相關屬性" // 提示說明
));
if (!LockedColor)
{
items.Add(new DesignerActionPropertyItem(
nameof(this.BackColor),
"背景顏色",
Header_Appearance,
"選擇背景顏色"));
items.Add(new DesignerActionPropertyItem(
nameof(this.ForeColor),
"前景顏色",
Header_Appearance,
"選擇前景顏色"));
// DesignerActionMethodItem 也可以加入 context menu 內 例如:designer verb
items.Add(new DesignerActionMethodItem(this,
nameof(this.InvertColors), // Method 名稱
"反轉前景和背景顏色",
Header_Appearance,
"反轉前景和背景顏色",
true));
}
items.Add(new DesignerActionPropertyItem(
nameof(this.Text),
"標籤文字",
Header_Appearance,
"設定標籤文字"));
// ColorLabel 相關資訊
items.Add(new DesignerActionTextItem($"位置:{colorLabel.Location}", Header_Information));
items.Add(new DesignerActionTextItem($"大小:{colorLabel.Size}", Header_Information));
return items;
}
}
}
建立 UserControl:ColorLabel需在 ColorLabel 上定義 Designer Attribute
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
namespace UCControlDesignerExample
{
/// <summary>
/// 標準控件 Label 延伸,新增 ColorLock Property 來使用
/// </summary>
[Designer(typeof(ColorLabelControlDesigner))]
public class ColorLabel : Label
{
public bool LockedColor { get; set; } = false;
public override Color BackColor
{
get
{
return base.BackColor;
}
set
{
if (LockedColor)
return;
else
base.BackColor = value;
}
}
public override Color ForeColor
{
get
{
return base.ForeColor;
}
set
{
if (LockedColor)
return;
else
base.ForeColor = value;
}
}
}
}
建立 DesignControlusing System.ComponentModel.Design;
using System.Security.Permissions;
using System.Windows.Forms.Design;
namespace UCControlDesignerExample
{
/// <summary>
/// ColorLabel 的智能標籤面板,必須引用 System.Design.dll
/// </summary>
[PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
public class ColorLabelControlDesigner : ControlDesigner
{
private DesignerActionListCollection actionLists;
public override DesignerActionListCollection ActionLists
{
get
{
if (null == actionLists)
{
// 加入智能面板內容
actionLists = new DesignerActionListCollection();
actionLists.Add(new ColorLabelActionList(this.Component));
}
return actionLists;
}
}
}
}
ColorLabel 使用效果
在 ColorLabel 控件上使用滑鼠右鍵,可以看見 [反轉前景和背景顏色] Method 可以使用
文章內提到的重點
總共有五點,只記錄有感的兩點
重點一:更新要透過 PropertyDescriptor 來完成
When a property or method in the class derived from DesignerActionList changes the state of the associated control, these changes should not be made by direct setter calls to the component's properties. Instead, such changes should be made through an appropriately created PropertyDescriptor. This indirect approach ensures that smart-tag undo and UI update actions function correctly.重點二:DesignerActionUIService.Refresh 來更新智能標籤,一開始閱讀時以為是更新控件效果,一整個誤導自己
You can dynamically update the smart-tag panel by calling DesignerActionUIService.Refresh. This process can be used to dynamically change the contents of the smart-tag panel. In the example, the smart tags concerned with changing colors are conditionally included depending on the state of the LockColors property. This Boolean property is also associated with a smart tag, so the developer can lock or unlock the current color selection, at least through the menu.
- 參考資料
- ControlDesigner 類別、DesignerActionListCollection 類別、DesignerActionList 類別、DesignerActionList.GetSortedActionItems 方法、PermissionSet 類別
- [C#.NET][Winform][User Control] 自訂控制項的智能標籤-ControlDesigner / User Control of Smart Tag-ControlDesigner
- Customizing User Controls with Smart Tag Feature
- .NET組件編程(7) Component DesignerAction(智能標記)
沒有留言:
張貼留言