I have a normal TextBox in Silverlight and the text in bound to models property. In the Setter of the property I check for some rules. If the rules say that value is invalid then I do not set the new value (instead the old one will be left or an other one).
Is there any way to inform the UI's TextBox that value changed. Because there is the only place in this Situation where the value is shown incorrect
(I tried ValidatesOnExceptions on BindingExpression and throw an exception in property, but nothing happened).
I know that using IValidation-Interface's is a better way. But for my current archytecture the above Scenario seems to be better.
Related
Every now and then I face a situation where I need to set a two-way binding on a property where it would be preferred that upon setting the binding the initial update will be performed in target-to-source direction and not source-to-target. That is, when the binding is set the source property value is updated so that it reflects the target property value, which stays unchanged.
Is such scenario possible? And if it is, how can it be accomplished?
Of course there are several workarounds, such as caching the target property value, setting the binding and then restoring the cached value, but I'm interested a direct answer rather than a workaround.
Example
Let's say we have a TextBox with Text property set to "foo". Also, we have a view-model with Name property (of type string) set to null. Now what I want to achieve is to bind the Text property to the Name property while preserving the "foo" value. Important thing here is to avoid setting Text to null and then back to "foo" (for whatever reason, e.g. because clearing the TextBox causes other controls to clear as well).
Then the best practice is 1) to read the existing value from the control (Clearly Xaml is not supposed to have data binding). 2) At "Load" event, the control needs to create and establish data binding by calling "SetBinding." 3) Finally get the binding expression for the control and update source with the value from 1).
All the code should be implemented in "View" code, not in "ViewModel."
e.g.) This code snippet is not tested, but has come from my head in the ball park.
private void Loaded(object sender, RoutedEventArg arg)
{
...
var text = textBox.Text;
var binding = new Binding();
... binding property here
textBox.SetBinding(TextBox.TextProperty, binding);
textBox.Text = text;
var expression = BindingExpression.GetBindingExpression(textBox, TextBox.TextProperty);
expression.UpdateSource();
}
How about creating an Attached Property that can be used to any UIElement? This should address the universality requirement.
<TextBlock Text="foo"
GlobalAttachedProperty:Value="{Binding Path=A_ValueFromVM_OR_SomeWhereElse}"
GlobalAttachedProperty:Property="Text"/>
The Value property just contain a callback to set the binding when there is a change. You can add some fancy routine that do this just once.
Then the Property is just a way to get the actual property for binding purposes. There are some other way to accomplish this but this is the more direct way.
I think that the best option is to set a default value in your model class. This is the purpose of the view model.
I have a form with some controls (say TextBox) which Text property is bound to some DataContext (say DataRowView).
I want to know if this row was filled correctly without any validation errors. I have found one possible solution. But I do not like it. It is not good to enum all the DependencyObjects on a form. Is there any way to enum only those DependencyObjects which was bound to this DataContext? May be some magic with BindingOperations...
How do you validate the input-data?
Maybe you could use a BindingGroup and then check it's Validation.HasError attached property.
I have a form with some textboxes in them that are bound to their properties in the VM through caliburn's automatic bindings. However if you type something on the textbox that does not make sense for the binding Caliburn simply does nothing with it ( or so I see it as ).
What I want to know if there is a way for Caliburn to constrain input to its binding in someway. For example:
I have a TextBox that is bound to a TimeSpan in the VM.
Writing 00:00:10 works fine and sets the TimeSpan to 10 seconds.
If I would write 00:00:-10 nothing happens and the binding remains at the previous value that did properly bind.
Your issue is not related to Caliburn.Micro that simply helps you connect your view to your view-model using data binding. What you need to use is validation of the data binding. You can read more about data binding in Silverlight in particular the Data Validation section is what you should study.
Caliburn.Micro automatically creates bindings using conventions. However, you may have to customize these bindings in XAML to get the desired validation behavior.
In the case where you write 00:00:-10 your validation fails because an exception is thrown from the binding engine's type converter. If the binding expression for the TextBox has a ValidatesOnExceptions property value set to true you will get visual feedback that the value is invalid. And because the entered value couldn't be converted to a TimeSpan no change is made to the view-model.
I have a a checkbox in XAML where i need the content to have a default value, lets say: "FooText", but also a binding to a field in an object, that can change.
The idea is that is that at load the checkbox should show the default content, but when an object is loaded the content should change accordingly.
Is this possible, and if so, how? I have some idea that i might be doable in a template, but since im pretty new to WPF i have no idea how to achieve the required result.
Im using the MVVM pattern.
Hope that someone might have a good idea:-D
You could use a default object for that, where you set all properties to the default value you want and then use it as DataContext.
Another thing is the TargetNullValue on Bindings. Using that you can set a default value to show if the target value of a binding is null.
It really depends on what you mean by "default value". WPF Databinding allows for a few ways to handle "default values":
FallbackValue: This allows you to specify a value if there is an issue with the databinding itself. For example, if you are binding to a property that does not exist on the viewmodel (DataContext).
TargetNullValue: This allows you to specify a value if the binding value is null, which is very possible for string values.
You can use both if you want to account for bad binding and null values, it's up to you. Either way, you should use FallbackValue often.
Create a checkboxContent property in viewmodel
set a default value to its private variable _checkboxContent = "FooText";
Bind this property to checkbox Content
When the object loads, assign the object property to checkboxContent property
I have a form with a textbox bound to an integer, and a button. Now, when the value of the textbox is invalid, I want to immediately disable the button.
Normally, one would put a Can() method in the VM, and trigger a NotifyOfPropertyChange in the property's setter. However, if the user inputs a non numeric value for example, the textbox is invalid, but the property setter is never called, so I can't notify/disable the button.
So, how do I disable the button, when the user inputs an invalid value that doesn't cause the property setter to get called? My knowledge of CM is limited as I've just started out.
I've found the best approach to this problem is to make the property a string instead and do the necessary string to integer conversion in your property setter. If the conversion is invalid, then you could reset the TextBox value to a default value. This way your property setter will always get fired.
If your model has an integer property, then it makes sense to place the string version on the view model, as this is only really related to the UI, rather than business logic.
If you don't wish the user to be able to input non digit characters, then you can use a masked text box, such as the one included in the Extended WPF Toolkit, or in a third party control suite such as those offered by Telerik or Infragistics.
I'd use a MaskedTextBox instead and set the mask to integer only.