Silverlight tri-state checkbox databinding to object property calculating value - silverlight

So I have this little problem making this to work:
I have silverlight client app that has custom usercontrol with tri-state checkbox with two-way binding
After user changes checkbox value, function underlying the property translates the value to integer:
-1 nothing
0 false
1 true
After user saves data from dialog box, all data(complex object) is being serializes and sent over to webservice and stored in SQL db.
When client requests saved data back from webservice, it get back that object OK
When I try to bind that returned deserialized object(EA) back to checkbox like this:
With cC
Dim b As New Binding("AllowedTo.Create")
b.Source = EA
b.Mode = BindingMode.TwoWay
.SetBinding(CheckBox.IsCheckedProperty, b)
End With
it only works ok if the values are true or false, but if value is nothing, as the checkbox is tri-state, it should turn to that third state - undefined - with minus sign [-], but it dosent.
It just stays at false state - empty with no check, like it would be false.
What could be the problem?
Sorry for my english, its not my mother language

Don't use an integer for this, use a Nullable Bool (Bool?). Two way binding works well, it converts:
Checked == true
Unchecked == false
Indeterminate == null
Serialization isn't a problem with nullable bools, in fact you don't even have to check if the SQL field value is NULL, since it will be a valid state, and using a bool field in the SQL database will even reduce it's size a bit ;)
If your database is set, and you can't change it, write a converter to convert your integer to a nullable bool for the binding, shouldn't take more then 2 minutes.

Since such a technique is really native to the checkbox, I would recommend creating a custom control to handle the 3 different states for that boolean value.

Related

Access Combobox is replacing empty string with null, then throwing error 3162

I have an Access form bound to linked view called vwBudgetEntries from SQL Server. The form contains a combo box bound to a field called SubcodeID which is short text and has the following properties:
Meanwhile, the row source of the combo box pulls a unique list of all subcode id's, including one where it's an empty string. For some reason, however, selecting this option throws the following error:
For the life of me, I can't figure out why. The value should be empty string, not null. If I change the combo box to a textbox and enter "", the update is accepted without any errors.
I've done what research I can and, so far, I've only found 2 workarounds:
Change the field properties to allow null, then replace null values with an empty string after the control updates.
Trap the error in the form_error event, undo the update and supply the value using VBA.
Neither workaround is ideal. Can someone explain why this error is occurring in the first place and what I might do to fix it?
Storing empty strings should be avoided for anything else than very special cases, or you will meet issues like this. So:
Set Required to No
Set Allow Zero Length to No
Store Null for the choice of unknown value for SubcodeID

Winforms ObjectListView: inner OLVColumn instances Name property is empty string so I cannot show/hide columns by name

This question is an offshoot of: Localizing ObjectListView OLVColumn, impossible due to Empty Name property
For simplicity's sake, let's say my ObjectListView contains car information. User A wants to display only Make and Model columns. User B only wants to display Model and Year columns. These preferences would be saved to/loaded from an .ini file on the users' local machines.
I cannot loop through the columns of the ObjectListView and do if (col.Name == colNameFromIni) { col.Visible == true; } because the .Name property of every column is an empty string ("") and does not get serialized to the designer codebehind file. This never happens with any other Winforms control (Label, Button, etc.) They always get their .Name written to the designer codebehind.
In some sense, this is a flaw in Winforms itself, because OLVColumn inherits from System.Windows.Forms.ColumnHeader, and a traditional ListView has exactly the same problem. .Name is always an empty string for all columns.
I would like to patch our local build of ObjectListView.dll to force populate the .Name property, but I can't figure out how Winforms automagically knows the name of every control on the form. It somehow(?) knows the names of the OLVColumn objects since it can display them in the Edit Columns... dialog on the ObjectListView's context menu. I'm also a little fuzzy on where the best spot is to plug this in.
(Yes, per linked question at top I know that as a last resort, I can hardcode colXX.Name = "colXX"; for all columns in my source code, but future column additions are likely to get overlooked and a programmatic solution is much preferred.)
(See also: https://sourceforge.net/p/objectlistview/bugs/160/ : the ObjectListView author declared this a wont-fix so it is up to me (or us), I guess.)
As you point out, this is a bug which is not with the ObjectListView, but the underlying component. And a bug which is around since at least 2008! Therefore, I doubt it will ever be fixed by MS.
Actually, it is a problem with the Autogenerated code in the designer.
If you look at other components such as a button, then the autogenerated code adds a name such as this;
//
// button2
//
this.button2.Location = new System.Drawing.Point(458, 199);
this.button2.Name = "button2";
...
But for ColumnHeader (Listview) and OLVColumn (ObjectListView), then this is not done, so then you end up with this.
//
// olvColumn1
//
this.olvColumn1.AspectName = "Name";
this.olvColumn1.Text = "Name";
If you manually add the line
this.olvColumn1.Text = "olvColumn1";
Then the "problem" is solved.
Of course, you can't do this, because the designer will override the autogenerated code when you make any changes, and then you will lose these manually added lines. It is also not sustainable.
So I'm afraid you need to code around this with some kind of ugly solution. Some options are:
Use the Tag to store the name and compare against this.
Use the text instead of the name (not possible if you have multi
language support!)
Code the names column manually in the Constructor
Set the Text to be something like "ColName;ColText" and then in your
code separate these out.
I have done option 3 in the past, but only I was maintaining the code, so this was easy.
What you could do to ensure you don't have discrepancies is to add a check in your constructor to compare the actual number of columns with the number you expect (hard coded for), and throw an exception if they don't match. Also, not the best, but another way to highlight and reduce errors.
The workaround for this is to get the OLVColumns via reflection and set their column's Name property at runtime. Every OLVColumn is a form-level field, so just pick them out of the list returned by GetFields().
Dim allFieldInfos As FieldInfo() = GetType(FrmMain).GetFields(BindingFlags.NonPublic or BindingFlags.Instance)
For Each fi As FieldInfo In allFieldInfos
If fi.FieldType Is GetType(OLVColumn) Then
Dim instance As OLVColumn = fi.GetValue(Me)
For Each col As OLVColumn In fdlvMain.AllColumns
If ReferenceEquals(col, instance) Then
col.Name = fi.Name
End If
Next
End If
Next

Difference between CoreceValueCallback and ValidateValueCallback?

I know that CoerceValueCallback is used to correct a value and that ValidateValueCallback will return true or false. But my question is why we need ValidatevalueCallback? We can simply use CoerceValueCallback to validate (using if condition) and correct the value. Can you give some practical example of when to use coercion vs. validation?
Here are the rules I follow for when to use coercion vs. validation.
Use CoerceValueCallback If...
You can safely correct a value to be valid without needing to throw an error.
Your property depends on one or more other dependency properties.
You need to provide instance-level validation as opposed to class-level validation.
You allow others to override your validation logic.
Use ValidateValueCallback If...
You cannot correct a value to be valid.
You must throw an error if an invalid value is provided.
You do not want others to override your validation logic.
So, it primarily depends on whether or not your property depends on other dependency properties or if you want others to be able to override your validation logic.
Since the ValidateValueCallback is not part of the PropertyMetadata, inheritors cannot modify the callback through the DependencyProperty.OverrideMetadata function.
Also, since the ValidateValueCallback does not provide your DependencyObject as a parameter, you cannot perform advanced validation that depends on other dependency properties.
Example 1
Suppose you have Minimum, Maximum, & Value properties. When any of these change, a CoerceValueCallback shoud be used to ensure the other properties are consistent.That is, Minmum <= Value <= Maximum.
However, assuming these values are doubles, then there are some values that would never make sense, namely Double.NaN, Double.PositiveInfinity, and Double.NegativeInfinity. Therefore, a ValidateValueCallback should be used to verify that the double values are normal, numeric values.
In fact, this is exactly how RangeBase works!
Example 2
Suppose you have a RegexTextBox control which takes a string containing a regular expression (call it RegexString). If a bad regular expression is provided, then what should be used instead? It might make sense to coerce it to be a null/empty value, rendering it useless; however, I suggest that this property be validated with a ValidateValueCallback. This is because any error is now thrown at compile-time when designing via the WPF designer.
For this property, there shouldn't be a CoerceValueCallback at all.
There is a whole lot of information describing how to use these callbacks.
I'd suggest taking a look at the MSDN article, Dependency Property Callbacks and Validation, for more in-depth knowledge.
Value coercion is basically to change the value, if the the new value is not as system expected. A best example is Slider control. A Slider has both Minimum and Maximum properties. Clearly, it would be a problem if the Maximum value were allowed to fall below the Minimum value. Value coercion is used to prevent this invalid state from occuring.
Validate value, is something that system will only check whether the given input is valid or not. It will throw Argument Exception if value is invalid (if we returned false for such value). For example, we have Age property, and it should be in range of 0 to 120. In case the new value is 500, the system may warn the user instead coercing it to some hardcoded value.
Any way both callbacks are optional and can be used based on the requirement.

PowerBuilder: Checkbox in DataWindow

I have a checkbox in the DataWindow, It can be checked and unchecked. The default value in the db is 0. When it's checked, the db value is updated to 1 and on uncheck, the value is updated to 0 again.
However, I want to update the database only if it has value 0. If it is already 1, then I don't want the user to be able to change it back to 0. So please tell me how can I do that?
Here is the code from my DataWindow for the checkbox column:
column=(type=decimal(0) update=yes updatewhereclause=yes name=ok dbname="table.ok" values="1/0" )
You could protect the checkbox to prevent unchecking it : in the general / protect field of your checkbox :
if(ok = 1, 1, 0)
Once the checkbox has been checked, it becomes protected (you still have to update the data to the base).
On the next retrieve, you can see that the checkbox is already protected.
You might have to use a similar expression for the Pointer to show that the field is blocked, for example with the NoPointer! cursor.
try using:
if( upper(ok) = 'OFF', 1, 0)
or the other way around:
if(upper(ok) = 'ON', 1, 0)
depending on how you set the on/off values in the properties of the check box.
Note I'm using PowerBuilder 2017

SmartGWT Dynamic Form edit record with boolean values

I've got following problem using SmartGWT 2.4:
we are having a DynamicForm showing several static text fields (so the form is in readonly mode). The form uses a datasource in the background and our own FormItemFactory to create proper form items based on our meta data. Some of the form items contain boolean values displayed as strings: like 'isHidden': false or 'canShow': true.
by user action (button click) we need to switch the form to edit mode.
We do it in following way:
we first gather the form values as rec = form.getValuesAsRecord() getting a Record object
then we create a new dynamic form and set into it the same datasource as original has
then we call the newForm.editRecord(rec) method of newly created dynamic form
This way the form static values are shown as editable input fields. However the problem is with those boolean values. They are correctly transformed into check boxes but all of them are checked by default.
I think that the string values 'false' or 'true' are not parsed into boolean values and set as value for respective check box item.
Can I somehow influence this process? I tried to provide an anonymous implementation of FormItemValueParser to CheckboxItem but it turns out to be use only by free text form items.
I'll be really thankful for any given hint.
Try setting the value explicitly to the formItem with record.getAttributeAsBoolean("formItemName")
BooleanItem boolItem = new BooleanItem("boolname");
DynamicForm form = new DynamicForm();
form.setItems(boolItem);
//Get record
Record rec = form.getValuesAsRecord();
boolItem.setValue("boolname",rec.getAttributeAsBoolean("boolname"));

Resources