I have a Winforms application with a DataGridView.
The DataSource of the grid is set to a BindingSource.
The DataSource of the BindingSource is a collection of objects, which implements the IBindingList interface. (Actually a SortableBindingList class based on a sample).
If I try to set the property AllowUserToAddRows on the grid, I get an error message "Property value is not valid" with additional details "Conversion from type 'Bitmap' to type 'Integer' is not valid."
Some of the columns in the grid show images, which are read-only.
What is this error message trying to tell me?
Are there some restrictions on the use of the property AllowUserToaddRows?
If it refers to a specific column in the grid, or a property in the class representing a row, how can I find out which column or property is causing the problem?
I've got it.
The error message is an exception in the function GetFormattedValue() in the custom implementations of DataGridViewImageCell.
In all of the real cases, this function is called with an enum value, which is displayed as an image. The function casts the value to the relevant enum and then selects one of several images.
If you set AllowUserToAddRows=true, then the designer calls the function GetFormattedValue and passes an image in the value parameter. My (poor) code generates an exception.
I have now added some handling for this case, and I can set AllowUserToAddRows to true.
Related
Why my IDataErrorInfo interfaced model validates text but not default windows int validation errors?
The IDataErrorInfo interface validation requires that the input value that is going to be updated to data source should get converted to the source type correctly.So the empty string field cannot be converted to int value correctly, so the source data will retain the original value and the IDataErrorInfo cannot notify the error.
You will need some custom validation rules here.
You can only set an int property to a valid int value and nothing else. It's not the resonsibility of a view model to validate that the view sets the property to an int. The type is part of the view model's API and the contract between the view model and any consuming class including the view.
This kind of validation is performed by the WPF framework itself. If you want to customize it, you could use a validation rule in the view or the control. There is an example available here.
But you can't do anything in the view model (except from changing the type of the property to string but this is generally a bad idea).
I'm binding my array of a abstract type with no problems to the datagrid. However, I just learned that a new property will be added and it's of type IEnumerable. I'm going to assume that the public properties of it are of type String.
How can I databind that new property so it displays anything useful in the datagrid? Testing a fake addition gives me only empty fields in that column. I can't split the new property into several columns because the count may vary.
Is it possible to achieve without explicit binding method at all?
I've got some hits when I searched but none of them gives me a clear answer. Possibly I'm just missing it due to confusion.
I have a DataTable which I bind to a DataGrid in WPF. No column generation is done in the XAML, everything is done when I create the DataTable in code.
I have 2 way binding, so the user can update the values in the DataGrid and it will update the DataTable, although this is not an event I can see when debugging, my results show it works as intended.
However if the type of a column is say double and the user enters text, the existing DataTable data for that cell is preserved, the cell is outlined in red and my debugger output shows a FormatException occurred.
What I am wanting to do is be able to either:
a) Handle this exception and show a warning to the user in my UI
b) Have some custom validation method which can set a flag in my code that I can use to handle the error at some point
I don't mind which solution I go with, I just don't want the user to not notice the error.
Thanks.
if you wanna stay with ado.net and datatables then: http://msdn.microsoft.com/en-us/library/1120xds5.aspx
EDIT:
this.MyTable.ColumnChanging += MyTableColumnChangingStuff;
private void MyTableColumnChangingStuff(object sender, DataColumnChangeEventArgs e)
{
if(e.Column.ColumnName == "MyColumnTestName")
{
var errormsg = MyValidateTestNameMethod(e.ProposedValue);
e.Row.SetColumnError(e.Column.ColumnName, errormsg);
}
//...
}
EDIT 2:
Thanks, just given that a try and while the event does get called when
I modify my data of the correct type, it does not get called if the
datatype the user inputs is wrong. The same as before happens, the box
is highlighted red and the format exception is handled by wpf, but the
event isn't called.
thats true. and there are just 2 solution for me. first create behaviors for your input controls where you can make sure that the values ALWAYS convertible to your underlying type. another solution would be thats your viewmodel where you bind to just have properties of type string. the nice thing with this is - that you never get a bindingexception because of casting a type. and what you have to do now is to implement IDataErrorInfo where you check your string property. and of course you have to cast your string values to the right type when you go to your model.
till now i use the first approach because i use datepicker, numeric behaviors and dont have any other types.
I have a textbox with a validator that permits only integer values. How do I check if text in my textbox represents a correct integer value without checking the text itself?
I am using Prism MVVM so I would like to hear some solution like "bind a validator property to your viewmodel/model code", but a generic WPF solution is also fine.
The problem is that I can't get the incorrect value in my model / viewmodel. If the value is incorrect, then the underlying binded property doesn't get set.
You could use IDataErrorInfo, or Data Annotations. The Data Annotations Extensions project contains an Integer attribute.
We are using the standard method for our controls to report broken BO rules. This is done via the interface IDataError in our BO’s and in XAML the control is bound to the BO’s property etc. This approach works OK. But we need to show 2 types of visuals in the UI depending on the type (or category if you like) of the invalidation error. If it’s a required field then we show a CueBanner (water mark) but for other types we change the colour of the controls boarder. In both scenarios we set the tool type of the error message.
The Problem with IDataError is that it doesn’t support a method/property to distinguish between error types.
The only way I can do that is by examining the error text, required field text must contain the key word “required”. The following approach doesn’t feel right but it’s the only way I can determine the type of error and then deal with it accordingly. All required field rules must have as part of the error text “required field”.
To make this all work I have created a custom dependency property called ErrorMessage. In my ResourceDictionary I have a Style.Trigger for Validation.HasError. In there I set my dependency properties value to the ErrorContent. Now when my dependency properties value changes I can examine the text and set the Validation.SetErrorTemplate( myControl, newErrorTemplate) to the template to suit the error type. I have to wire up a few events to the control such as lost and got focus to manage removing or adding the cueBanner template but the whole thing will work. It’s just that I’m not sure it’s the best way to do it.
PS. When I set the ErrorTemplate i’m doing this in code, thats building and adding it. Is there a way to point Validation.SetErrorTemplate to a static resource keeping in mind that I need to switch between at least 2 types?
Your thoughts please..
Would it be possible to derive an interface IDataError that adds an extra property which is an enumeration of the error type. Then you could try and bind against it.
If you're okay with an (untested)approach that suffers a little bit of clarity, then you could do the following:
throw an exception instead of returning an string with the IDataErrorInfo Interface. In your ErrorTemplate, you can access the ValidationErrors (and the ValidationError.Exception Property).
Then, you use a DataTrigger on the Exception in combination with a converter, that checks for the right Exception-Type and return true or false. It should be enough to do the job.