I have a BindingList called bList that is getting utilized in a GUI.
public BindingList<SomeList> bList = new BindingList<SomeList>();
What I'm trying to do is change the RowStyle with an event by checking a property in bList. Let's say in bList I have 6 objects which have multiple properties. One of the properties in bList I have is called isValid, which is a bool, if that's set to false I turn that row red, else the row just stays the default color.
I was able to get all rows turning red if they are >= 0. How can I iterate over bList to find the property isValid for each object in blist?
private void gridView_RowStyle(object sender, RowStyleIEventArgs e)
{
bool isValid = class.bList[0].isValid;
if (e.RowHandle >= 0)
{
if (isValid == false)
{
e.Appearance.BackColor = Color.Red;
}
}
}
You should use reflection to get the property value of your object. Here is a sample function that will work for a generic BindingList.
Use:
for (int i = 0; i < myList.Count; i++)
{
object val = null;
TryGetPropertyValue<SomeType>(myList, i, "isValid", out val);
bool isValid = Convert.ToBoolean(val);
// Process logic for isValid value
}
Method:
static private bool TryGetPropertyValue<T>(BindingList<T> bindingList, int classIndex, string propertyName, out object val)
where T : class
{
try
{
Type type = typeof(T);
PropertyInfo propertyInfo = type.GetProperty(propertyName);
val = propertyInfo.GetValue(bindingList[classIndex], null);
return val != null; // return true if val is not null and false if it is
}
catch (Exception ex)
{
// do something with the exception
val = null;
return false;
}
}
In order to change the color of a row based on a property value, you should add that property as a hidden column and then use that cell's value to set the style.
See the following:
How to change a row style based on a column value
For your problem:
private void gridView_RowCellStyle(object sender, DevExpress.XtraGrid.Views.Grid.RowCellStyleEventArgs e)
{
string valid = gridView.GetRowCellValue(e.RowHandle, "isValid").ToString().ToLower();
if(valid == "true")
e.Appearance.BackColor = Color.Red;
}
To add a hidden column:
Hide Column in GridView but still grab the values
I'm now able to iterate over the BindingList bList because I had some other issues with inheritance trying to figure out what type for the iterator.
foreach (SomeType item in bList)
{
if (e.RowHandle >= 0)
{
if (instance.isValid == false)
{
e.Appearance.BackColor = Color.Red;
}
else
{
e.Appearance.BackColor = Color.White;
}
}
}
How come all the rows are still turning red even though I'm finding which object with the property isValid is returning false.
Related
I am trying to make a bool property that would toggle the pwdLastSet property.
public bool UserMustChangePassword
{
get { return (long)Entry.Properties["pwdLastSet"].Value == 0; }
set
{
if (value)
{
Entry.Properties["pwdLastSet"].Value = 0;
}
else
{
Entry.Properties["pwdLastSet"].Value = -1;
}
}
}
I can set the property successfully however I cant read the property. I keep getting the following casting error.
System.InvalidCastException: 'Specified cast is not valid.'
Is there a specific way to read this property. I know it may be possible to UserPrincipal, however I would like to use DirectoryEntry to keep the code consistent.
Edit: check null before casting
public bool UserMustChangePassword
{
get
{
var value = Entry.Properties["pwdLastSet"].Value;
if (value != null)
return (long)Entry.Properties["pwdLastSet"].Value == 0;
return false;
}
set
{
if (value)
{
Entry.Properties["pwdLastSet"].Value = 0;
}
else
{
Entry.Properties["pwdLastSet"].Value = -1;
}
}
}
You need to check its Count property to make sure there is a value. Try this,
if (Entry.Properties["pwdLastSet"].Count > 0)
{
return (Entry.Properties["pwdLastSet"][0] == 0)
}
else
return false;
Edit:
Seems the problem comes from that you are querying Properties of DirectoryEntry instead of SearchResult. See this question. I have a copy of working code that is also querying SearchResult.
I am trying to implement a delete functionality in my DataGridView to clear the contents of highlighted cells.
One of the columns contains a double, and when the value is less than zero I display it as blank. If the user edits the cell to blank, this is handled via the CellParsing event.
The DataGridView is databound using a BindingSource and BindingList.
The issue I'm having is that when I change the cell Value to blank via my clear function, the CellParsing event does not fire and I get a FormatException saying that "" is not a valid value for Double. When the user clears the cell, the CellParsing event fires and everything happens as expected.
The reason I am setting the value to blank is that some of the columns are text and others are numbers, and I'd like to be able to delete them all at once.
I've googled and searched through StackOverflow and haven't found something yet that will solve my issue. Is there a way to route this through the CellParsing event or some other obvious solution that I'm missing?
See the CellParsing and clearing code below.
System::Void dataGridViewWells_CellParsing(System::Object^ sender, System::Windows::Forms::DataGridViewCellParsingEventArgs^ e)
{
//Handle blank values in the mass column
e->ParsingApplied = false;
if(this->dataGridViewWells->Columns[e->ColumnIndex]->HeaderText == "Mass (ng)")
{
if(e->Value->ToString() == "" || e->Value->ToString() == " ")
{
e->Value = -1.0;
e->ParsingApplied = true;
}
}
}
void DeleteHighlightedCells(DataGridView^ dgv)
{
try
{
System::Windows::Forms::DataGridViewSelectedCellCollection^ sCells = dgv->SelectedCells;
for(int i = 0; i < sCells->Count; i++)
{
if(!sCells[i]->ReadOnly)
{
dgv->Rows[sCells[i]->RowIndex]->Cells[sCells[i]->ColumnIndex]->Value = "";
}
}
}
catch(Exception^ e)
{
LogError("Unable to delete contents of DataGridView cells: " + e->ToString());
}
}
System::Void dataGridViewWells_KeyDown(System::Object^ sender, System::Windows::Forms::KeyEventArgs^ e)
{
if(e->Control && e->KeyCode == Keys::C)
{
this->CopyContentsToClipBoard(this->dataGridViewWells);
}
if(e->Control && e->KeyCode == Keys::V)
{
this->PasteContentsFromClipBoard(this->dataGridViewWells);
}
if(e->KeyCode == Keys::Delete)
{
this->DeleteHighlightedCells(this->dataGridViewWells);
}
}
I ended up abandoning the CellParsing event and putting in a custom TypeConverter for my class property as was done in this question.
TypeConverter code:
public ref class MassTypeConverter : System::ComponentModel::TypeConverter
{
public:
virtual bool CanConvertFrom(System::ComponentModel::ITypeDescriptorContext^ context, Type^ sourceType) override
{
return sourceType == String::typeid || System::ComponentModel::TypeConverter::CanConvertFrom(context, sourceType);
}
virtual Object^ ConvertFrom(System::ComponentModel::ITypeDescriptorContext^ context, System::Globalization::CultureInfo^ culture, Object^ value) override
{
if(value != nullptr && value->GetType() == String::typeid)
{
//
double converted;
bool success = double::TryParse((String^)value, converted);
if(((String^)value) == "" || ((String^)value) == " ")
{
converted = -1.0;
success = true;
}
if(success)
{
return converted;
}
}
return System::ComponentModel::TypeConverter::ConvertFrom(context, culture, value);
}
};
And then put the following above my class Property:
[System::ComponentModel::TypeConverter(MassTypeConverter::typeid)]
I have a datagridview where one of the columns is a color column. I want to ensure the user enters a valid color, otherwise leave the cell blank.
When the cell is starting from blank, the following code gives me a null reference exception. Fyi, I am doing this in the CellLeave event.
Answer I had to move the code to the CellFormatting event. For some reason, the value at the cell does not get updated until a certain unknown point. For my check, I need to do it before something I was doing in the CellFormatting event. Moving the code there fixed my problem.
private void dataGridView1_CellFormatting(object sender, DataGridViewCellEventArgs e)
{
if (e.ColumnIndex.Equals(2))
{
Regex test = new Regex("[0-255],[0-255],[0-255]");
Match m = test.Match(this.dataGridView1.CurrentCell.Value.ToString());
if(!m.Success)
{
this.dataGridView1.CurrentCell.Value = "";
}
}
}
To validate a string you could use this method:
private static bool IsValidColorString(string input)
{
if (String.IsNullOrEmpty(input))
return false;
string[] parts = input.Split(',');
if (parts.Length != 3)
return false;
foreach (string part in parts)
{
int val;
if (!int.TryParse(part, out val) || val < 0 || val > 255)
return false;
}
return true;
}
The best place to use it I believe is the DataGridView.CellParsing event handler:
private void dataGridView1_CellParsing(object sender, DataGridViewCellParsingEventArgs e)
{
if (e.Value == null || e.ColumnIndex != 2) // Skip empty cells and columns except #2
return;
string input = e.Value.ToString();
if (!IsValidColorString(input))
e.Value = String.Empty; // An updated cells's value is set back to the `e.Value`
}
An updated cells's value is set back to the e.Value instead of the DataGridView.CurrentCell.Value.
Try this for your match:
Match m = test.Match((this.dataGridView1.CurrentCell.Value ?? "").ToString());
This will replace a null value with an empty string when matching.
Do you perhaps need to check to see if there is a value within the cell before you try and match a Regex?
if (e.ColumnIndex.Equals(2))
{
if(this.dataGridView1.CurrentCell.Value != null)
{
...
CurrentCell.Value.ToString()
Causing the error..
CurrentCell.value=null
null value can't cast using the tostring() method,that's why you are getting ther null reference exception.
try this..
string val="";
if(dataGridView1.CurrentCell.Value==null)
{
val=""
}
els
else
{
val=convert.tostring(dataGridView1.CurrentCell.value);
}
Match m = test.Match(val);
if(!m.Success)
{
this.dataGridView1.CurrentCell.Value = "";
}
I have a Devexpress gridcontrol that has a checkbox column in it. I am trying to get the value of the checkbox value after user checks or unchecks one of the checkbox in any row. My problem is I am getting the always getting false value.
How can I get the correct value? what event should I use?
here is my code,
private void gvBobin_CellValueChanged(object sender, DevExpress.XtraGrid.Views.Base.CellValueChangedEventArgs e)
{
setUsageSlipAndProductionEntryRelation();
}
public void setUsageSlipAndProductionEntryRelation() {
for (int i = 0; i < gvBobin.RowCount -1; i++)
{
bool check_ = (bool)gvBobin.GetRowCellValue(i, "CHECK");
if (check_ == true)
{
...............
}
else{
...............
}
}
}
If you want to immediately react to user actions, then you need to use GridView.CellValueChanging event. GridView.CellValueChanged event is fired only after user leaves the cell. In both cases to get the changed value you must use CellValueChangedEventArgs object e and its Value property and before getting value you must to check the column.
private void gvBobin_CellValueChanged(object sender, DevExpress.XtraGrid.Views.Base.CellValueChangedEventArgs e)
{
if (e.Column.FieldName == "CHECK")
{
bool check_ = (bool)e.Value;
if (check_)//There are no need to write check_ == True
//You can use e.RowHandle with gvBobin.GetRowCellValue method to get other row values.
//Example: object value = gvBobin.GetRowCellValue(e.RowHandle,"YourColumnName")
{
//...............
}
else
{
//...............
}
}
}
If you want to iterate through all rows then don't use GridView.RowCount. Use GridView.DataRowCount property instead.
for (int i = 0; i < gvBobin.DataRowCount -1; i++)
//...............
I'm attempting to iterate through all the textboxes in my WPF window to see if they are empty, and if they are, the method should set a bool to true.
private void checkTextBoxes(DependencyObject obj)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
{
if (obj is TextBox && ((TextBox)obj).Text == null)
{
isTextBoxEmpty = true;
}
}
}
isTextBoxEmpty is my bool that has been defined outside of the method. I call the method using:
checkTextBoxes(this);
But the bool always returns false no matter what I do, even if all the text boxes are empty.
Try to change this :
((TextBox)obj).Text == null)
To this :
(String.IsNullOrEmpty((TextBox)obj).Text))
The result you got possibly because TextBox's Text is never null, it is empty string ("") by default, thats what I think, just possibly.
Outside of any syntax errors this should give you the result you expect; This only returns true if ALL textboxes are blank
private void checkTextBoxes(DependencyObject obj)
{
var trueforall = true;
var atleastone = false;
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
{
if (obj is TextBox)
{
if(!atleastone){ atleastone = true;}
trueforall &= string.IsNullOrWhiteSpace(((TextBox)obj).Text);
if (!trueforall) { break; }
}
}
isTextBoxEmpty = trueforall && atleastone;
}