Mam problem z prawidłową obsługą zdarzenia zmiany wartości w kolumnie typu DataGridViewCheckBoxColumn (kolumna z CheckBox-ami w DataGridView).
Potrzebuję mieć obsługę zmiany wartości zaznaczenie w tej kolumnie natychmiast po zmianie zaznaczenia (kliknięcie lub zmiana za pomocą spacji).
Wygląda na to że system wykrywa taką zmianę (zdarzenie Validating) dopiero po opuszczeniu danej celi, a tutaj chodzi o reakcję natychmiast po wykonaniu zmiany.
Czy ktoś już się spotkał z takim problemem?
Jeżeli tak, to będę wdzięczny za wszelkie uwagi na ten temat.
tak.. ostatnio u mnie w pracy wymagano podobnego efektu i jeszce kilku innych wodotryskow jak np. podswietlenie na czerwono jak wartosc wprowadzona jest zla i skonczylo sie na tym ze musialem stworzyc wlasna subklase kolumn, subklase komorki, subklase panelu kontrolki edycyjnej i dostarczyc wlasna kontrolke edycyjna.. a prawidlowa obsluga powiazan pomiedzy nimi to to mozna pol ksiazki napisac..
ogolnie, podczas normalne pracy, datagridview w ogóle nie interesuje sie faktem ze cos w niego wpisujesz. on reaguje dopiero po skonczonej edycji pola --- czyli utracie przez to pole focusu. masz sporo szczescia i nieszczescia ze operujesz na checkboxach. nieszcescie polega na tym, ze te checkboxy nieistnieja. sa udawane - obiekt komorki datagridviewa rysuje je 'z palca' i udaje ich zachowanie. szczescie masz natomiast w tym, ze obiekt komorki udostepnia event OnClick - podepnij sie pod niego w sposob
winitializeczygdziesindziej()
{
(komorka as datagridviewcheckboxcell).Click += new eventhandler(datagridviewcell_click);
}
private blahblah datagridviewcell_click(sender, args)
{
if( (sender as datagridviewcheckboxcell).Checked )
//blah
else
//blah
}
musisz tylko spradzic czy sender rzeczywiscie bedzie obiektem komorki -- mozliwe ze bedzie obiektem datagrida, wtedy gorzej, no ale lapiesz o co chodzi :)
Moment kliknięcia wychwycisz przez CellClick, spację przez KeyPress. Rozwiązanie może niezbyt eleganckie, ale za to łatwe w implementacji.
Dzięki za odpowiedź :)
Próbowałem już ze znarzeniami OnClick i KeyPresses dla DataGrida, ale wtedy jest problem ze zbadaniem faktycznego stanu klikanej komórki, ponieważ DataGrid widzi ciągle "starą" wartość, która zmienia się dopiero po zmianie focus-a - tak jak napisałeś.
Nie próbowałem jeszcze z podpinaniem zdarzeń bezpośrednio do celi. Zaraz tego spróbuję i dam znać o efektach.
Jeste tylko drobny problem.
DataGridViewCheckBoxCell nie ma publicznego zdarzenia Click
(używam VS .NET 2005, .NET Framework 2.0)
Jest działające rozwiązanie dla klienkięcja myszką:
private void datagridview_CellMouseUp(object sender, DataGridViewCellMouseEventArgs e)
{
datagridview.CommitEdit(DataGridViewDataErrorContexts.CurrentCellChange);
Do_Sth_On_Selection_Chenge();
}
// Musi być MuseUp, bo inaczej źle wykrywa dwuklik - generuje tylko jedno zdarzenia, a tak naprawdę w CheckBox-ie stan zmienia się 2 razy
private void Do_Sth_On_Selection_Chenge()
{
// ...
}
To samo rozwiązanie nie działa prawidłowo dla klawiatury (sprawdziłem dla zdarzenia KeyPressed i KeyUp - źle wykrywa stan zaznaczenia komórki - coś jest nie tak z kolejnością zatwierdzania zmian w komórkach). Ale trzeba szukać dalej :)
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
DataGridViewCheckBoxColumn column = new DataGridViewCheckBoxColumn();
column.Name = "Column1";
column.HeaderText = "Column1";
dataGridView1.Columns.Add(column);
for (int i = 0; i<10;i++)
{
dataGridView1.Rows.Add();
dataGridView1.Rows[i].Cells[0].Value = false;
}
this.dataGridView1.CellMouseUp += new System.Windows.Forms.DataGridViewCellMouseEventHandler(this.dataGridView1_CellMouseUp);
this.dataGridView1.CellValueChanged += new System.Windows.Forms.DataGridViewCellEventHandler(this.dataGridView1_CellValueChanged);
this.dataGridView1.KeyUp += new System.Windows.Forms.KeyEventHandler(this.dataGridView1_KeyUp);
}
private void dataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
MessageBox.Show(dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Value.ToString());
}
private void dataGridView1_CellMouseUp(object sender, DataGridViewCellMouseEventArgs e)
{
if (e.ColumnIndex == 0 & e.RowIndex >= 0)
{
dataGridView1.EndEdit();
}
}
private void dataGridView1_KeyUp(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Space)
{
dataGridView1.SelectedCells[0].Value = !((bool)dataGridView1.SelectedCells[0].Value);
dataGridView1.EndEdit();
}
}
}
A tu zupełnie działające rozwiązanie. :) Zwróć uwagę na to, że metody wiążę ze zdarzeniami dopiero po napełnieniu DataGrida (!).
Wielkie dzięki!
Jesteś WIELKI.
Nie wiem tylko czemu zwracasz uwagę na kolejność 1. wypełnianie data grida 2. podłaczenie metod.
Ja zrobiłem standardowo (metody podłączone w designerze - czyli odpala się na konstuktorze), a wypełnianie DataGrida mam później.... i działa idealnie!!
Jeszcze raz wielkie dzięki!!
Zarejestruj się i dołącz do największej społeczności programistów w Polsce.
Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.