2012-09-26 27 views
2

我已經設置了用戶控件的FlowPanelLayout在這個問題上的幫助: For Each DataTable Add UserControl to FlowLayoutPanel選擇用戶控件從FlowLayoutPanel的

我現在想實現一個click事件,讓我把邊框已被用戶控件選擇。我已經做到了這一點:

 private void User_Load(object sender, EventArgs e) 
    { 
     flowlayoutpanelUsers.HorizontalScroll.Visible = false; 

     // Load and Sort Users DataTable 
     DataTable datatableUsers = UserMethods.GetUsers().Tables["Users"]; 
     datatableUsers.DefaultView.Sort = "Name"; 
     DataView dataviewUsers = datatableUsers.DefaultView; 

     // Loop Through Rows and Add UsersGrid to FlowLayoutPael 
     foreach (DataRowView datarowviewUsers in dataviewUsers) 
     { 
      var UsersGrid = new UsersGrid 
      { 
       Username = datarowviewUsers["Username"].ToString(), 
       User = datarowviewUsers["Name"].ToString(), 
       Admin = datarowviewUsers["Administrator"].ToString(), 
      }; 
      flowlayoutpanelUsers.Controls.Add(UsersGrid); 
      UsersGrid.MouseClick += new MouseEventHandler(user_click); 
     } 
    } 

    private UsersGrid selectedUser; 

    void user_click(object sender, EventArgs e) 
    { 
     if (selectedUser != null) 
      selectedUser.BorderStyle = BorderStyle.None; 
     selectedUser = (UsersGrid)sender; 
     selectedUser.BorderStyle = BorderStyle.FixedSingle; 
    } 

我的問題是,它只有當我在用戶控件白色空間點擊而不是當用戶點擊兩個標籤或形象工程。我如何使它適用於所有子對象?

此外,我怎樣才能使用選定的UserControl做其他事情,比如打開一個顯示所選用戶的所有細節的窗體?

+0

我猜UsersGrid是你的用戶控件? –

+0

@JustinSkiles - 是的。對不起,我應該解釋一下。 – hshah

回答

4

我爲你提供了一些建議。在我的迴應的底部,我包含了能夠證明我的建議的代碼。

建議1:在你的UC鼠標點擊固定
當您註冊一個用戶控件(UC)的鼠標點擊事件你這樣做的用戶控件本身,而不是爲你放置在用戶控件,如任何控件您的標籤等。如果您點擊其中一個子控件,則點擊將不會被底層UC所「看到」。

要解決此問題,請爲您的所有子控件註冊MouseClick事件;您甚至可以爲UserControl本身註冊相同的MouseClick事件處理程序。

建議2:設置你的UC的邊框
我將你的代碼設置UC的BorderStyle到UC本身。創建公共屬性IsSelected,在選擇UC時設置爲true。在財產的設置者更新加州大學的BorderStyle屬性取決於財產的價值。

爲您的UC公開一個IsSelected屬性可能很方便:您可以查詢一組這些UC來查看哪些是被選中的,而不是像通過Form-level變量那樣嘗試跟蹤控件之外的這種狀態。

編輯迴應您的評論:
這裏有一個如何查詢一個FlowLayoutPanel中的UCS,看看是否有任何選擇的一個例子,如果發現你怎麼可能採取一些行動。在這種情況下,動作是調用EditUser方法,它的參數值,你從選定UC性能得到:

var selectedUC = flowLayoutPanel.Controls.Cast<UserControl1>().FirstOrDefault(uc => uc.IsSelected); 
if (selectedUC != null) { 
    // Use the properties of the UC found to be selected as parameters is method EditUser. 
    EditUser(selectedUC.Name, selectedUC.Username, selectedUC.Administrator); 
} 

建議3:一組你的UCS的管理選擇
如果你想要取消選擇用戶點擊(即選擇)組中的所有UC,則需要在UC中創建一個點擊UC時觸發的事件。此事件的處理程序明確地將IsSelected設置爲對於集合中的所有UC(例如在諸如Form,FlowLayoutPanel等的容器類型控制中)的假,則被點擊的UC中的MouseClick處理器然後將設置單擊的UC的IsSelected爲真。

值得考慮創建另一個管理一組UCs的UserControl類型。這個新的UserControl可以封裝你的UC的創建和狀態管理的代碼,並且會促進在其他項目中使用你的UCs,並且讓託管你的UCs的表單更加清潔。


我想,而不是包括一系列脫節的代碼片段,我的每個建議,我想包括我希望是什麼的代碼,讓你重現什麼我談論的最低金額。

創建一個新的Visual Studio的Winform項目,並使用Form1類以下內容:

public partial class Form1 : Form 
{ 
    public Form1() { 
     InitializeComponent(); 

     flowLayoutPanel = new FlowLayoutPanel { 
      Dock = DockStyle.Fill, 
     }; 
     this.Controls.Add(flowLayoutPanel); 
     // Add several sample UCs. 
     for (int i = 0; i < 10; i++) { 
      var uc = new UserControl1(); 
      uc.WasClicked += UsersGrid_WasClicked; 
      flowLayoutPanel.Controls.Add(uc); 
     } 
    } 

    FlowLayoutPanel flowLayoutPanel; 

    // Event handler for when MouseClick is raised in a UserControl. 
    void UsersGrid_WasClicked(object sender, EventArgs e) { 
     // Set IsSelected for all UCs in the FlowLayoutPanel to false. 
     foreach (Control c in flowLayoutPanel.Controls) { 
      if (c is UserControl1) { 
       ((UserControl1)c).IsSelected = false; 
      } 
     } 
    } 
} 

下一個用戶控件添加到項目中。保留名稱UserControl1並添加一對標籤和一個PictureBox。使用此代碼UserControl1類:

public partial class UserControl1 : UserControl 
{ 
    public UserControl1() { 
     InitializeComponent(); 
     this.Load += UsersGrid_Load; 
    } 

    // Event fires when the MouseClick event fires for the UC or any of its child controls. 
    public event EventHandler<EventArgs> WasClicked; 

    private void UsersGrid_Load(object sender, EventArgs e) { 
     // Register the MouseClick event with the UC's surface. 
     this.MouseClick += Control_MouseClick; 
     // Register MouseClick with all child controls. 
     foreach (Control control in Controls) { 
      control.MouseClick += Control_MouseClick; 
     } 
    } 

    private void Control_MouseClick(object sender, MouseEventArgs e) { 
     var wasClicked = WasClicked; 
     if (wasClicked != null) { 
      WasClicked(this, EventArgs.Empty); 
     } 
     // Select this UC on click. 
     IsSelected = true; 
    } 

    private bool _isSelected; 
    public bool IsSelected { 
     get { return _isSelected; } 
     set { 
      _isSelected = value; 
      this.BorderStyle = IsSelected ? BorderStyle.Fixed3D : BorderStyle.None; 
     } 
    } 
} 
+0

老兄,這太神奇了。我只是改變了一些變量名稱,以使它與我的標準匹配,並將BoderStyle設置爲FixedSingle。 – hshah

+0

道歉,如果我問得太多,但是sa y我想選擇一個UC,然後點擊一個按鈕或雙擊它打開一個新的表單,用戶可以編輯該特定用戶,我該怎麼做?基本上我的計劃是該表單將包含名稱,用戶名和管理員字段,用戶可以編輯並將其保存回數據庫。我已經對數據庫進行了讀/寫,所以我們已經對它進行了排序,以瞭解UC已被選擇,以便在新表單上顯示適當的細節。 – hshah

+1

@hshah我編輯了建議#2與我的迴應。要根據UC監控的事件(例如點擊)執行相同的事情,您可以創建自己的'EventArgs'類型(擴展'EventArgs'),其中包含您關心的UC中的字段的屬性('Name'等)。當您在UC中引發此事件時,您可以將這些字段填充到您的自定義'EventArgs'類型中,並將它們讀回到Form中的事件處理程序中。 –

0

您可以嘗試訂閱UserControl上的GotFocus事件。

警告:

Because this event uses bubbling routing, the element that receives focus might be a child element instead of the element where the event handler is actually attached. Check the Source in the event data to determine the actual element that gained focus.

UIElement.GotFocus Event

UPDATE

這個問題可能是適當的:Click event for .Net (Windows Forms) user control

+0

不幸的是,我不知道這意味着什麼,甚至不知道如何實現它:( – hshah

+0

@hshah,檢查我的編輯,這個網站上有一個關於處理與UserControls點擊事件的問題的鏈接 –

+0

我做了一些嘗試就像在UserControl中那樣,但是當它從窗體中調用它時,它選擇了每個被單擊的用戶控件,並且在另一個用戶單擊時沒有取消選擇它:( – hshah

1

我知道這是老了,但我在這裏登陸尋找如何做UC選擇在集裝箱一些指點。 傑伊的答案效果很好。

只需一次更新:UsersGrid_Load方法將只涉及頂級控件,容器的子項將不參與WasClicked事件。

private void UsersGrid_Load(object sender, EventArgs e) { 
    // Register the MouseClick event with the UC's surface. 
    this.MouseClick += Control_MouseClick; 
    // Register MouseClick with all child controls. 
    RegisterMouseEvents(Controls); 
} 

添加遞歸方法RegisterMouseEvents到該用戶控件

private void RegisterMouseEvents(ControlCollection controls) 
    { 
     foreach (Control control in controls) 
     { 
      // Subscribe the control to the 
      control.Click += Control_MouseClick; 
      if (control.HasChildren) RegisterMouseEvents(control.Controls); 
     } 
    }