How to control two-way binding initial update direction - c#

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.

Related

How to create TwoWay binding between two DependencyProperties in code? [duplicate]

I have heard a lot about two-way bindings in WPF, but I'm not entirely clear on how to accomplish it or what it actually means.
I have a ListView with a bunch of items in it. When the user selects a new item, a TextBox in the application will change its text to display some property of the selected item.
But when the user changes the text in the text box I want the ListView item to be updated immediately as well. Is there any "two-way binding" magical WPF way of accomplishing this?
Mark's answer shows how to accomplish what you want, but you also asked more generally about "how to accomplish [two-way binding] and what it actually means."
One-way binding means that the binding target (e.g. control) will display data from the binding source (e.g. business object), and will update itself as the business object changes, but that changes to the control will not be propagated back to the business object. E.g. if the Person.Name changes from "bob" to "kate", the TextBlock.Text bound to the Name will change from "bob" to "kate" too.
Two-way binding simply means that not only are changes in the business object reflected in the UI, but changes made by the user in the UI are propagated back to the business object too. So now when the user edits the TextBox.Text bound to the Name, say changing "kate" to "edmund", WPF will set the Person.Name property to "edmund" as well.
To accomplish this, just set Mode=TwoWay on the Binding declaration. Some properties bind two-way by default: TextBox.Text, for example, binds TwoWay by default, which is why Mark's code doesn't need the Mode declaration. In addition, as Mark notes, by default WPF only propagates changes back to the business object when the control loses focus. If you have two UI elements bound to the same property, this can mean they appear out of sync, in which case you can use the UpdateSourceTrigger to force WPF to propagate whenever the property changes.
MSDN covers this in detail with some good clear diagrams: see Data Binding Overview in the WPF SDK.
If you haven't you'll need to implement INotifyPropertyChanged for your class that you're binding to.
Also, when you say you want the ListBox item to be updated immediately, you mean that you want it to change as you type in the TextBox. By default the TextBox.Text property updates its source when it loses focus, but you can change this by setting the binding UpdateSourceTrigger to PropertyChanged:
{Binding Source={...}, Path=Whatever, UpdateSourceTrigger=PropertyChanged}
What is the Type of the items in the ListView? To get the two way binding going the need you implement INotifyPropertyChanged...
This might help WPF event property changed?

Validation of Controlvalue with binding in Property Setter

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.

Checkbox with both a default content values as well as one from binding

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

Binding vs Explicit Assignment of a Variable

I am thinking about the following issue.
If I have for example a textbox/slider/combobox which value is bound to something like
<TextBox Name=textBox Text="{Binding Text}"/>
and then do
textBox.Text = "something"
Is it going to "override" the binding or is binding "stronger" then explicit assignment
No, the binding will be overwritten.
No it won't update your binding. Binding gets updated only when it comes from View, if you set it from your code behind, it will override the text but will break the binding. You can try this sample -
Place a textbox on your view and bind it's text property to some
property in your viewmodel say value for this property is "Test"
Now place two button's on your view.
On first button click simply set the text of your textbox to
something say "Button1".
You will notice that textbox text will now be "Button1" but still the value of your CLR property will be "Test".
Now on second button click, try to set your Viewmodel property to say
"Button2". PropertyChanged will be fired but you won't notice any
change in your textbox text.
If you want to update the binding, you have to set the Dependency property from your code behind like this-
textBox.SetCurrentValue(TextBox.TextProperty, "Button2");
where textBox is your name of the TextBox.
Just simply put the value you will like to be in the textbox in the "Text" memeber of the bound object. Otherwise the binding will be overwritten, as devdigital mentioned above.

Swapping data binding in code

I have two data-bound text boxes. One is bound to a string and the other to a number. The 'default' binding is set in XAML. Under some circumstances I need to reverse the bindings at runtime (the string is usually a prefix but sometimes it's a suffix).
I have the following code in my view model, called when the window is loaded:
Binding stringBinding = BindingOperations.GetBinding(view.seqLeft, TextBox.TextProperty);
Binding numberBinding = BindingOperations.GetBinding(view.seqRight, TextBox.TextProperty);
view.seqLeft.SetBinding(TextBlock.TextProperty, numberBinding);
view.seqRight.SetBinding(TextBlock.TextProperty, stringBinding);
After that the code loads the properties to which the binding refers.
The problem is that the 'new' binding doesn't seem to work. What have I missed? Is there a better way?
I might consider exposing Prefix and Suffix strings to which View can bind, then use logic within the ViewModel, or whatever backing object you're using, to fill those strings accordingly. This option neatly segments the business concern from the visual and simplifies what you have to keep track of in your view.
Why monkey around with the bindings at all? If you want to have a TextBox that's bound to one of two different things, create two TextBoxes, put them in the same location, and toggle their visibility based on whatever your swap condition is.
The only thing wrong with my code was the TextBlock.TextProperty in the SetBinding calls! They should, of course, have been TextBox.TextProperty but I'd messed with it so long I wasn't seeing the wood for the trees.

Categories