WPF datagrid oddity - wpf

I've been implementing a way to 'tick all' checkboxes in my datagrid.
public void SelectAllCheckboxes(object sender, RoutedEventArgs e)
{
if (bindSource != null)
{
DataView list = (DataView)bindSource.List;
System.Windows.Controls.Button btn = e.OriginalSource as System.Windows.Controls.Button;
if (btn.Content.ToString() == "Select All")
{
for (int i = 0; i < list.Count; i++)
{
list[i]["Approve?"] = true;
}
}
else
{
for (int i = 0; i < list.Count; i++)
{
list[i]["Approve?"] = false;
}
}
bindSource.DataSource = list;
dataGrid.DataContext = bindSource;
}
}
When I use the method once to tick all checkboxes, it works fine. All checkboxes are ticked. However, when I try to 'select none' to untick everything the first checkbox will never ever change. The tick stays there.
This also happens in the reverse order of selection.
The datarow does retain the intended true/false value, it's just not represented on the grid.
What on earth is going on?
[edit]After some further testing, the checkbox works properly after I "wake it up" by clicking on it a few times and changing its ticked value. Very very strange.

Related

Determine whether the active check box is checked in Winforms

I am developing a Windows Forms Application using Visual Studio in Visual C++. My form has 96 check boxes on it. Rather than create 96 Click events, I believe that there's a way to create a single Click event that is called when any check box is clicked. Within the Click event, I need to determine whether the active checkbox is Checked or Not Checked. While this should be easy, I can't seem to figure it out!
I got it to work with the code below, but I'm sure there's a better way.
if (sender == checkBox_D1)
{
if (checkBox_D1->Checked)
isChecked = true;
}
else if (sender == checkBox_D2)
{
if (checkBox_D2->Checked)
isChecked = true;
}
else
return; // Invalid sender - should not get here!
if (isChecked)
{
// Do something
}
else
{
// Do something else
}
I also tried the code below but activeCheckBox is not a Checkbox object so it doesn't work.
Control^ activeCheckBox = ActiveControl;
activeCheckBox->Text returns the Text property of the Checkbox
activeCheckBox->Checked doesn't compile. The error is 'Checked' : is not a member of 'System::Windows::Forms::Control'
It seems like sender has the data that I need but I don't know how to access it.
Is there a way to declare a Checkbox as follows?
CheckBox activeBox;
and then assign activeBox to the Checkbox that has the focus
activeBox = ???
// Then just need to do this!
if (activeBox.Checked)
isChecked = true;
Thank you for the help.
Yes you can reuse the same function for all your Check boxes.
void App3::ItemPage::checkBox_Checked(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
{
CheckBox^ activeCheckBox = safe_cast<CheckBox^>(sender);
if (activeCheckBox->Checked)
{
if (activeCheckBox->Name == "checkBox_D1") {
//Do something when this check box is clicked.
}
if (activeCheckBox->Name == "checkBox_D2") {
//Do something when this check box is clicked.
}
}
}
For all checBoxes you will assign the same CheckedChanged event:
checkBox1.CheckedChanged += newCheckBoxCheckedOrUnchecked_CheckedChanged;
checkBox2.CheckedChanged += newCheckBoxCheckedOrUnchecked_CheckedChanged;
//...
//...
checkBox95.CheckedChanged += newCheckBoxCheckedOrUnchecked_CheckedChanged;
checkBox96.CheckedChanged += newCheckBoxCheckedOrUnchecked_CheckedChanged;
Checks the state of all checkBoxes:
private void newCheckBoxCheckedOrUnchecked_CheckedChanged(object sender, EventArgs e)
{
foreach (Control control in this.Controls)
{
if (control.GetType() == typeof(CheckBox))
{
var checkBox = (CheckBox) control;
var checkBoxName = checkBox.Name; // To know which checkbox we are talking about
var checkBoxIsChecked = checkBox.Checked;
// Do your stuff
MessageBox.Show(checkBoxName + #" is " + (checkBoxIsChecked ? "checked" : "not checked"));
}
}
}
Checks the state of only the checkBox where the value was changed:
private void newCheckBoxCheckedOrUnchecked_CheckedChanged(object sender, EventArgs e)
{
var checkBox2 = (CheckBox)sender;
var checkBoxName2 = checkBox2.Name; // To know which checkbox we are talking about
var checkBoxIsChecked2 = checkBox2.Checked;
// Do your stuff
MessageBox.Show(checkBoxName2 + #" is " + (checkBoxIsChecked2 ? "checked" : "not checked"));
}

How to create radiobuttons programatically on a datagridview

I'm using C# in Visual Studio 2010. I have a datagridview on a winform. I would like 1 column to contain radio buttons only. Each row would have 3 radio buttons. I'm not sure I understand what is needed for that. Any help would greatly be appreciated.
create a DataGridViewCheckBoxColumn and connect to the CellContentClick event. then use this code:
private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
if (e.ColumnIndex == 0)// checkbox column
{
object curr =
dataGridView1[e.ColumnIndex, e.RowIndex].Value;
if (curr == null || (bool)(curr) == false)
{
for (int i = 0; i < dataGridView1.RowCount; i++)
{
if (i != e.RowIndex)
{
dataGridView1[e.ColumnIndex, i].Value = false;
}
}
}
}
}

RepositoryItemCheckEdit doesn't stay checked

I try to add a RepositoryItemCheckEdit to my GridView using devexpress and Winforms. However, I can get only one checkbox be checked. If I check another one, the checkbox I checked before becomes unchecked. I followed everything I can find on the net, but couldn't make this work. What am I missing?
The code part I insert the column:
gcIsEmirleri.DataSource = (from i in isemirleri
select new
{
ID = i.isEmriId,
// other attributes
}).ToList();
GridColumn column = gvIsEmirleri.Columns["Sec"];
if (column == null)
{
gvIsEmirleri.BeginUpdate();
DataColumn col = new DataColumn("Sec", typeof(bool));
column = gvIsEmirleri.Columns.AddVisible("Sec");
col.VisibleIndex = 0;
col.Caption = "Sec";
col.Name = "Sec";
col.OptionsColumn.AllowEdit = true;
gvIsEmirleri.EndUpdate();
gvIsEmirleri.Columns["Sec"].UnboundType = DevExpress.Data.UnboundColumnType.Boolean;
RepositoryItemCheckEdit chk = new RepositoryItemCheckEdit();
chk.ValueChecked = true;
chk.ValueUnchecked = false;
gvIsEmirleri.Columns["Sec"].ColumnEdit = chk;
chk.QueryCheckStateByValue += chk_QueryCheckStateByValue;
}
The code part I make the checkbox two-stated instead of three:
private void chk_QueryCheckStateByValue(object sender, DevExpress.XtraEditors.Controls.QueryCheckStateByValueEventArgs e)
{
if (e.Value == null)
{
e.CheckState = CheckState.Unchecked;
e.Handled = true;
}
}
EDIT: I created a List<bool> chkList; and do the following operations:
This function is added to checkedits' CheckStateChanged:
private void chk_CheckStateChanged(object sender, EventArgs e)
{
CheckEdit chk = sender as CheckEdit;
if (chk.Checked)
chkList[gvIsEmirleri.FocusedRowHandle] = true;
else
chkList[gvIsEmirleri.FocusedRowHandle] = false;
FillBindingSource();
}
In FillBindingSource I added the lines:
for (int i = 0; i < chkList.Count; i++)
{
if (chkList[i])
gvIsEmirleri.SetRowCellValue(i, "Sec", true);
}
I debug these lines, I see that List has correct bool values and gvIsEmirleri.SetRowCellValue(i, "Sec", true); is operated when it has to. However, it still doesn't work.
My guess is : You are using an unbound Column, and you are not saving the checked / unckecked info, so, after the selected row is left, the checkBox get it's initial value (unckecked).
For this, I suggest you handle the CustomUnboundColumnData event of your view. Here is a simple :
readonly Dictionary<object, bool> checkedMap = new Dictionary<object, bool>();
private void viewScales_CustomUnboundColumnData(object sender, CustomColumnDataEventArgs e)
{
// Check what column
if (e.Column != gvIsEmirleri.Columns["Sec"])
return;
if (e.IsGetData)
{
// check if the row has been checked and set it's value using e.Value
bool checked;
if (checkedMap.TryGetValue(e.Row, out checked))
e.Value = checked;
}
if (e.IsSetData)
{
var checked = Convert.ToBoolean(e.Value);
// Check if the key already exist
if (checkedMap.ContainsKey(e.Row))
scaleMap.Remove(e.Row);
checkedMap.Add(e.Row, checked);
}
}
Note : This is the way I resolved a similar problem, but I did not test the code I just wrote.

TextBox resets text when tabbing out ot other controls

I have a form with several controls. There a situtions where 'textBoxOtherRelationship' is disable and the text is set to string.empty. But when I then got to another control and tab out the data appears again,while the control remains disabled.
textBoxOtherRelationship.DataBindings.Add(new Binding("Text", _binder, "RelationshipNotes"));
private void ComboBoxRelationShipSelectedValueChanged(object sender, EventArgs e)
{
if ((Constants.Relationship)comboBoxRelationShip.SelectedItem.DataValue == Constants.Relationship.Other)
{
textBoxOtherRelationship.Enabled = true;
if (_formMode != ActionMode.ReadOnly)
{
textBoxFirstName.BackColor = Color.White;
}
}
else
{
textBoxOtherRelationship.Enabled = false;
_model.RelationshipNotes = null;
textBoxOtherRelationship.Text = string.Empty;
if (_formMode != ActionMode.ReadOnly)
{
textBoxFirstName.BackColor = Color.LightYellow;
}
}
}
Hmm.. so I see this line here:
textBoxOtherRelationship.DataBindings.Add(
new Binding("Text", _binder, "RelationshipNotes"));
which tells me that you've got binding set up between the Text property on the textBoxOtherRelationship and a property called "RelationshipNotes" on the datasource _binder.
Great.
So, I'm assuming that the two-way binding works just fine and that when you type something into the textBoxOtherRelationship and that control loses focus the underlying RelationshipNotes property is getting updated as well, right?
Now, looking at your code there, I don't think the underlying datasource is being updated when you set the Text property to string.Empty because that usually doesn't happen until the textbox loses focus and you've disabled the control.
If you add:
textBoxOtherRelationship.DataBindings[0].WriteValue();
after you set the value to string.Empty that string.Empty value will get stored back to the datasource because the databinding will know there is something to update. Programmatically, it doesn't.
I see you have this line:
textBoxOtherRelationship.Enabled = false;
_model.RelationshipNotes = null; <<<----------------------
textBoxOtherRelationship.Text = string.Empty;
Is _model.RelationshipNotes what is ultimately supposed to be bound to that textbox?
The SelectedIndexChanged event doesn't commit the databindings until after the control loses focus, so the quick fix is to write the value first in your event:
private void ComboBoxRelationShipSelectedValueChanged(object sender, EventArgs e)
{
if (comboBoxRelationShip.DataBindings.Count > 0) {
comboBoxRelationShip.DataBindings[0].WriteValue();
if ((Constants.Relationship)comboBoxRelationShip.SelectedItem.DataValue ==
Constants.Relationship.Other) {
textBoxOtherRelationship.Enabled = true;
if (_formMode != ActionMode.ReadOnly) {
textBoxFirstName.BackColor = Color.White;
}
} else {
textBoxOtherRelationship.Enabled = false;
_model.RelationshipNotes = null;
textBoxOtherRelationship.Text = string.Empty;
if (_formMode != ActionMode.ReadOnly) {
textBoxFirstName.BackColor = Color.LightYellow;
}
}
}
}

How can I Hide the first row for UniformGrid Control?

UnifomGrid has loaded Data, I want to Hide the first row?
How can I implement that?
I've never worked with the UniformGrid so there might be a better solution for this but as far as I can tell the UniformGrid doesn't hold much information except how many rows and columns it currently have so therefore this is the only solution that I can think of.
private List<UIElement> GetElementsAtRow(int rowNumber)
{
List<UIElement> elementsAtRow = new List<UIElement>();
for (int i = 0; i < uniformGrid.Columns; i++)
{
if (i < uniformGrid.Children.Count)
{
elementsAtRow.Add(uniformGrid.Children[i] as UIElement);
}
}
return elementsAtRow;
}
private void HideFirstRow()
{
List<UIElement> elementsAtRow = GetElementsAtRow(0);
foreach (UIElement element in elementsAtRow)
{
// Or Hidden if you want row to remain but with no Visible children.
element.Visibility = Visibility.Collapsed;
}
}
private void ShowFirstRow()
{
List<UIElement> elementsAtRow = GetElementsAtRow(0);
foreach (UIElement element in elementsAtRow)
{
element.Visibility = Visibility.Visible;
}
}

Resources