2010-01-19 10 views
9

Używam formantu CheckedListBox w małej aplikacji, nad którą pracuję. To miła kontrola, ale jedna rzecz mnie niepokoi; Nie mogę ustawić właściwości, aby sprawdzała tylko element, gdy faktycznie zaznaczam pole wyboru. Jaki jest najlepszy sposób na pokonanie tego? Zastanawiam się nad uzyskaniem pozycji kliknięcia myszką, względną po lewej stronie pola wyboru. Który działa częściowo, ale gdybym kliknął puste miejsce, na tyle blisko po lewej, bieżący wybrany element byłby nadal sprawdzany. Wszelkie pomysły dotyczące tego?Kontrola CheckedListBox - zaznaczanie pola wyboru tylko wtedy, gdy kliknięto faktyczne pole wyboru

+0

Może brakuje mi czegoś. Co się dzieje teraz, gdy zaznaczasz pole? Nic? Czy to domyślnie sprawdza? Co się dzieje, że chcesz przestać? – hunter

+0

Chcę, aby to pole było zaznaczone, gdy kliknę pole, a nie linię. Wyobraź sobie, że wygląda to następująco: [] Item1 Obecnie pole jest sprawdzane po kliknięciu w cały element, ale nie chcę tego. Chcę tylko, aby został kliknięty, gdy kliknę to pole, a nie tekst opisowy obok niego. – Oxymoron

+0

można użyć dodatkowej etykiety, tylko listy wyboru, a następnie utworzyć etykiety, .. to nie jest tak dobrze rozwiązany, ale działa:> – Tyzak

Odpowiedz

7

Cóż, jest to dość brzydki, ale można obliczyć myszy hit współrzędne przeciwko prostokątów przedmiotów, zaczepiając na CheckedListBox.MouseDown i CheckedListBox.ItemCheck jak na poniższym

/// <summary> 
/// In order to control itemcheck changes (blinds double clicking, among other things) 
/// </summary> 
bool AuthorizeCheck { get; set; } 

private void checkedListBox1_ItemCheck(object sender, ItemCheckEventArgs e) 
{ 
    if(!AuthorizeCheck) 
     e.NewValue = e.CurrentValue; //check state change was not through authorized actions 
} 

private void checkedListBox1_MouseDown(object sender, MouseEventArgs e) 
{ 
    Point loc = this.checkedListBox1.PointToClient(Cursor.Position); 
    for (int i = 0; i < this.checkedListBox1.Items.Count; i++) 
    { 
     Rectangle rec = this.checkedListBox1.GetItemRectangle(i); 
     rec.Width = 16; //checkbox itself has a default width of about 16 pixels 

     if (rec.Contains(loc)) 
     { 
      AuthorizeCheck = true; 
      bool newValue = !this.checkedListBox1.GetItemChecked(i); 
      this.checkedListBox1.SetItemChecked(i, newValue);//check 
      AuthorizeCheck = false; 

      return; 
     } 
    } 
} 
+0

Tak, jak powiedziałem w OP, myślałem też o czymś takim, ale ponieważ nie czuje się naprawdę dobrze, zacząłem szukać alternatywy :) – Oxymoron

+2

Dzięki, po prostu działa! Niektóre optymalizacje są możliwe, ale pomysł działa! – nightcoder

0

Tekst pola wyboru w CheckedListBox jest domyślnie renderowany, aby umieścić etykietę HTML po wprowadzeniu pola wyboru i ustawić atrybut "dla" etykiety na identyfikator tego pola wyboru.

Gdy etykieta oznacza element, dla którego jest "dla", kliknięcie tej etykiety powoduje, że przeglądarka koncentruje się na tym elemencie, który właśnie widzisz.

Dwie opcje to renderowanie własnej listy z osobnymi elementami kontrolnymi i tekstem CheckBox (nie jako właściwością Text kontrolki CheckBox, ponieważ działa to tak samo jak CheckBoxList), jeśli lista jest statyczna lub używa czegoś takiego jak repeater jeśli lista jest dynamiczna.

+0

To nie jest formularz internetowy, ale winform :) Ale dostaję swój dryf. Koncentracja jest w porządku, a właściwie to, czego chcę, po prostu nie chcę, by zaznaczone było pole wyboru po kliknięciu na element. Wygląda na to, że będę się bawić z niestandardową formantką :) – Oxymoron

+0

Ok, trudno powiedzieć, kiedy jako znaczniki były tylko C# i CheckedListBox. Poszedłem dalej i dodałem winFormy. –

9

Znam ten wątek jest trochę stary, ale don” sądzę, że to problem zaoferować inne rozwiązanie:

private void checkedListBox1_MouseClick(object sender, MouseEventArgs e) 
{ 
    if ((e.Button == MouseButtons.Left) & (e.X > 13)) 
    { 
     this.checkedListBox1.SetItemChecked(this.checkedListBox1.SelectedIndex, !this.checkedListBox1.GetItemChecked(this.checkedListBox1.SelectedIndex)); 
    } 
} 

(z wartością CheckOnClick = True).

Możesz użyć tej rzeczy z prostokąta, ale dlaczego sprawić, by było bardziej skomplikowane, co trzeba.

5

Innym rozwiązaniem jest po prostu użycie widoku drzewa.
Ustaw CheckBox na true, ShowLines na false, a ShowPlusMinus na false i w zasadzie to samo co CheckedListBox. Pozycje są sprawdzane tylko po kliknięciu faktycznego CheckBox.

CheckedListBox jest znacznie bardziej uproszczony, ale TreeView oferuje wiele opcji, które potencjalnie mogą lepiej pasować do twojego programu.

0

Spróbuj tego. Zadeklaruj iLastIndexClicked jako zmienną int poziomu formularza.

private void chklst_MouseClick(object sender, MouseEventArgs e) 
{ 
    Point p = chklst.PointToClient(MousePosition); 
    int i = chklst.IndexFromPoint(p); 
    if (p.X > 15) { return; } // Body click. 
    if (chklst.CheckedIndices.Contains(i)){ return; } // If already has focus click anywhere works right. 
if (iLastIndexClicked == i) { return; } // native code will check/uncheck 
    chklst.SetItemChecked(i, true); 
    iLastIndexClicked = i; 
} 

Wystarczy sprawdzić, czy użytkownik kliknął w skrajnej lewej 15 pikseli sprawdzonej listy (obszar pola wyboru) pracuje przez cały czas z wyjątkiem ponownego sprawdzania aktualnie wybrany element. Przechowywanie ostatniego indeksu i wychodzenie bez zmiany pozwala natywnemu kodowi poprawnie obsłużyć, próbując ustawić to na sprawdzone, w tym przypadku włącza się i po prostu wyłącza, gdy działa kod "ItemCheck".