您好,我的代碼有問題。我在表單上添加了 44 個標簽,并嘗試以這種方式為每個標簽制作 2 個事件處理程式:
/// <summary>
/// Adds event handler methods to all Label controls on current form using foreach loop,
/// these handlers handle MouseDown and MouseMove events
/// </summary>
public void AddEventToLabels()
{
foreach (Control c in this.Controls)
{
if (c.GetType() == typeof(Label))
{
c.MouseDown = new MouseEventHandler(this.Label_MouseDown);
c.MouseMove = new MouseEventHandler(this.Label_MouseMove);
}
}
}
/// <summary>
/// Executes when button of mouse is pressed by user and cursor is over the control
/// </summary>
/// <param name="sender">The source of the event</param>
/// <param name="e">Provides data for the MouseUp, MouseDown, and MouseMove events</param>
public void Label_MouseDown(object sender, MouseEventArgs e)
{
md.StoreMouseLocation(e); //Just a method to store location of cursor
}
/// <summary>
/// Executes when user moves mouse and cursos is over the control
/// </summary>
/// <param name="sender">The source of the event</param>
/// <param name="e">Provides data for the MouseUp, MouseDown, and MouseMove events</param>
public void Label_MouseMove(object sender, MouseEventArgs e)
{
var label = sender as Label; //Casts sender object to control on current form
md.MoveControl(e, label); //Moves label with cursor
}
但是這些處理程式不起作用,我不明白為什么。好吧,我怎樣才能讓它正常作業?
uj5u.com熱心網友回復:
問題是關于控制的父級。我需要在指定的容器中迭代所有這些控制元件,因為它是所有需要的控制元件的父級。所以我用foreach (Control c in this.<ParentName>.Controls)代替foreach (Control c in this.Controls)
uj5u.com熱心網友回復:
每個Control(表單、用戶控制元件,還有按鈕、文本框等)都有零個或多個子控制元件。它們可以通過屬性Control.Controls訪問
您想為表單中的所有標簽訂閱事件 MouseDown 和 MouseMove。
當然,您希望按照正確的面向物件的思想作業,因此您將關注點分開。除其他外,您可以通過制作只有一項任務的小方法來做到這一點。這樣你的方法將更容易理解、更好地重用、更容易維護、更改和單元測驗。
所以你給你的 Form 幾個屬性:
public IEnumerable<Control> SubControls => this.Controls.Cast<Control>();
IEnumerable<Lable> Labels => this.SubControls.OfType<Label>();
為了提高效率,您可以更改最后一個:
IEnumerable<Lable> Labels => this.Controls.OfType<Label>();
但我假設您不會每秒呼叫該方法十次,所以我不會打擾:可維護性是這里的關鍵。
在我看來,您想實作拖放標簽。
- 滑鼠按下:開始拖動標簽:保存必須移動的標簽;保存滑鼠按下位置
- 滑鼠移動:如果我們正在拖動標簽,請將標簽放置在滑鼠位置
- 滑鼠向上:停止拖動標簽。
拖動時label的位置不是滑鼠位置,而是滑鼠位置 mousedown時的偏移量。
Size DragLabelOffset {get; set;} = Size.Empty;
在拖動開始時,DragLabelOffset 將是要拖動的標簽的位置與拖動開始時滑鼠位置之間的差值。拖動時,標簽的位置為當前滑鼠位置 DragLableOffset。
void StartDragDropLabel(Label label, Position mouseDownPosition)
{
this.DraggedLabelOffset = new Size(mouseDownPosition.X - label.Location.X,
mouseDownPosition.Y - label.Location.Y);
}
void DragLabel(Label label, Position mousePosition)
{
label.Location = mousePosition this.DraggedLabelOffset;
}
void StopDragLabel(Label label, Position mousePosition)
{
// not sure if this is needed: set final drag position
this.DragLabel(label, mousePosition);
this.DragLabelOffset = Size.Empty; // indicate: no drag is active
}
事件處理程式:
void Label_MouseDown(object sender, MouseEventArgs e)
{
Label label = (Label)sender;
this.StartDragDropLabel(label, e.Location);
}
void Label_MoveMove(object sender, MouseEventArgs e)
{
Label label = (Label)sender;
this.DragLabel(label, e.Location);
}
void Label_MouseUp(object sender, MouseEventArgs e)
{
Label label = (Label)sender;
this.StopDragLabel(label, e.Location);
}
訂閱滑鼠事件:
void SubscribeLabelsToMouseEvents()
{
foreach (Label label in this.Labels)
{
label.MouseDown = this.Label_MouseDown;
label.MouseMove = this.Label_MouseMove;
label.MouseUp = this.Label_MouseUp
}
盡管舊代碼用于 create new EventHandler(...),但不需要這樣做,現代編譯器將在沒有 EventHandler 的情況下理解這一點。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/339208.html
上一篇:如何對控制元件型別串列進行排序
