Skip to main content
Home Forums Silverlight Programming Programming with .NET - General Abort binding in ConvertBack method & Getting DataContext
10 replies. Latest Post by silverstarter on June 29, 2009.
(0)
MightyBob
Member
12 points
44 Posts
03-26-2009 6:10 AM |
Hi,
I have two questions:
Question 1:I would like to abort a binding if an incorrect value is received in the ConvertBack method of an IValueConverter class. Here is the simple example code:
Question 2:I would also like to get the datacontext of the object that activated the ConvertBack method, to be able to update other parts of the DataContext if an acceptable value was received. For example, a Person object gets a Salary value passed to the ConvertBack, but if it is a valid salary, I would also like to update the SalaryDate for the Person.
I have previously done this by catching the sender as a Textbox (before I used Converters) and simply getting a new instance of Person and setting it to the Textbox.DataContext value. Easy. But now I'm unsure how to do that with a Converter.
Thanks in advance! By the way, love this forum! Every question I have had so far has been answered! Incredible!
/MightyBob
mehtapratik
269 points
302 Posts
03-26-2009 7:58 AM |
for the second question, you can use like this, it's not a good way, but i am doing in the following way.
public class ValueConverter : System.Windows.Data.IValueConverter { PermissionTypes objPermissionTypes; public ValueConverter() { if (objPermissionTypes == null) objPermissionTypes = new PermissionTypes(); } #region IValueConverter Members public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { Int32 intCounter = 0; for (int i = 0; i < objPermissionTypes.PermissionTypeList.Count; i++) { if (objPermissionTypes.PermissionTypeList.id == (int)value) { return objPermissionTypes.PermissionTypeList; } intCounter++; } return null; } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { return ((BWS.PermissionTypeService.PermissionType)value).id; } #endregion }
03-26-2009 10:13 AM |
In regards to Question 1, could I somehow pass the textbox itself as a parameter? Would that work, and if so, how would I do that?
<TextBox x:Name="txtTo" Text="{Binding ElementName=txtFrom, Path=Text, ConverterParameter=[****THIS TEXTBOX****], Converter={StaticResource Converter}}"
Anyone?
03-26-2009 10:16 AM |
may be you have to pass old value so if the value is not matched with your criteria you can bind it with old value.
03-26-2009 10:28 AM |
mehtapratik: may be you have to pass old value so if the value is not matched with your criteria you can bind it with old value.
Sure, sounds good, but how do I pass the old value? And, maybe you know how to pass the entire TextBox so I could access the DataContect value too?
sbrato
258 points
03-26-2009 10:57 AM |
Hello,
It seems to me that the converters you are creating are doing more than they should (but I may not fully understand your requirements). A converter used in a bindind should just convert values from one type to another and it's not the place to do validation or other datacontext object updates.
For your second question, when a UI control is databound to a property in a dataContext, the binding will call the setter for that property when the input in the UI control changes. Therefore, for your example, when the Salary of a person receives a good value, the setter will get called, and it's in that setter that you should update other fields like SalaryDate. It's not clear to me why whould you make these updates in the Converter.
For the first question, it seems you want to do validation in the converter code. If you decide in the converter that you cannot convert, you should return back the same object. Back to the Salary example.. if you get an object in the converter that cannot be converted to a float, just return it back unconverted. The binding engine will fail to call the Salary property and it will raise BindingValidationError event (if you set NotifyOnValidationError=true and ValidatesOnExceptions=true). You can then handle BindingValidationError and do whatever you want there (including reverting back the value by just settign the Text on the TextBox to the value of the Salary property (which note that it didn't get changed since the binding engine failed to call the constructor).
BTW, Silverlight 3 beta includes build-in validation support. In your case, if something invalid is passed to the Salary text-box, the build-in validation in SL3 will automatically highlight the field and display ui error cues
Hope this helps
03-26-2009 11:12 AM |
sbrato: Hello, It seems to me that the converters you are creating are doing more than they should (but I may not fully understand your requirements). A converter used in a bindind should just convert values from one type to another and it's not the place to do validation or other datacontext object updates. For your second question, when a UI control is databound to a property in a dataContext, the binding will call the setter for that property when the input in the UI control changes. Therefore, for your example, when the Salary of a person receives a good value, the setter will get called, and it's in that setter that you should update other fields like SalaryDate. It's not clear to me why whould you make these updates in the Converter. For the first question, it seems you want to do validation in the converter code. If you decide in the converter that you cannot convert, you should return back the same object. Back to the Salary example.. if you get an object in the converter that cannot be converted to a float, just return it back unconverted. The binding engine will fail to call the Salary property and it will raise BindingValidationError event (if you set NotifyOnValidationError=true and ValidatesOnExceptions=true). You can then handle BindingValidationError and do whatever you want there (including reverting back the value by just settign the Text on the TextBox to the value of the Salary property (which note that it didn't get changed since the binding engine failed to call the constructor). BTW, Silverlight 3 beta includes build-in validation support. In your case, if something invalid is passed to the Salary text-box, the build-in validation in SL3 will automatically highlight the field and display ui error cues Hope this helps
Hi sbrato,
Thanks for your input! To be honest, I was not aware of setters. I'm pretty new to Silverlight. If I have a datagrid bound to a collection of Persons, couls you show me how to apply the logic you suggested? What I want, is if someone alters the salary for the person in the datagrid (editable textbox), I want the value of Person.salary_date (datetime) to be set to the current date.
Regards,
03-26-2009 2:42 PM |
To get an understanding on how the databinding works (this in not realated with dataGrid.. it's applicable to all the controls) please take a look at http://silverlight.net/learn/tutorials/databinding.aspx .
When you databind a DataGrid to a collection of items, every row represent an item in that collection, and every cell maps to a certain property on that Item. In your's case, the cell for the salary is dataBound to the Salary property defined in your Person class. When you edit the cell and supply a valid value, the setter for the Salary gets called and it's there where I would say it's the best place to update SalaryDate. For e.g.
public class Person { public float Salary { get { return _salary; } set { _salary=value; SalaryDate=DateTime.Now; } } public DateTime SalaryDate { get; set; } }
03-27-2009 4:24 AM |
sbrato: Hello, To get an understanding on how the databinding works (this in not realated with dataGrid.. it's applicable to all the controls) please take a look at http://silverlight.net/learn/tutorials/databinding.aspx . When you databind a DataGrid to a collection of items, every row represent an item in that collection, and every cell maps to a certain property on that Item. In your's case, the cell for the salary is dataBound to the Salary property defined in your Person class. When you edit the cell and supply a valid value, the setter for the Salary gets called and it's there where I would say it's the best place to update SalaryDate. For e.g. public class Person { public float Salary { get { return _salary; } set { _salary=value; SalaryDate=DateTime.Now; } } public DateTime SalaryDate { get; set; } }
Ah, now I see. How beautifully simple! I guess the most simple answers are the ones you get caught up on the most ha? ;) I will try it immediately, but I'm sure it will be just what I need. Oh, and I'm sorry for seeming a bit confused in my earlier post, I thought you were talking about setters in XAML (the ones you use for templates and so, I think, I haven't been able to read up on those yet), not property get/set. Duh... Hahaha! Anyways, thanks! I'll give it a try at once.
03-27-2009 4:52 AM |
It worked like a charm!
Thanks alot!
silverst...
216 points
146 Posts
06-29-2009 11:09 AM |
ok, to make it a little bit more complicated:
what if i bind a datevalue and use a string-datetimeConverter?
the problem is.. it can be a wrong syntax like 17.70 or even a word instead of time.. how can i write back the old value into the textbox if it was wrong?
ty
silverstarter