OneWayToSource Dilemma
wpf, wpf-4.0, xaml
Solution
The `Content` property can only be set to a single value, and you are replacing the value "756" with a binding.
As I pointed out to you in my answer to your other question, WPF runs the code in this order:
- Normal - Constructors run here
- DataBind
- Render
- Loaded
So the first thing that is done is your `MainWindow` Constructor is run. This creates the button, which calls the Button's constructor, and sets `Button.Content` to "765".
However in the XAML for the `Button`, you have specified a different `Content` property - a binding. So your button object gets created, the `Content` property gets set to "765", and then the `Content` property is set to `{Binding Path=Txt, Mode=OneWayToSource}`.
This is the same as doing something like:
var b = new MyButton();
b.Content = "756";
b.Content = new Binding(...);
You are replacing the `Content` property.
(And technically, the last line should be `b.SetBinding(MyButton.ContentProperty, new Binding(...));` to bind the value correctly, however I am using a more basic syntax to make it easier to understand the problem.)
The next step in the cycle is Data Binding, so the binding on the `Content` property is evaluated.
Since it is a `OneWayToSource` binding, the property only updates the source element when it gets changed, and since this is the first time the binding is being evaluated, it sets the source to whatever the default is for this `DependencyProperty` so they're synchronized.
In the case of the `Button.Content` dependency property, the default value is `null`, so your source element gets set to `null`.
You don't see this behavior with `TwoWay` bindings because the DP gets it's value from the binding instead of using the default value.
If you were to set your value after the binding has been set up, such as in the `Loaded` event for your button, you would see that your source property correctly gets updated when you set your Button's `Content`
void MyButton_Loaded(object sender, EventArgs e)
{
((Button)sender).Content = "756";
}
And last of all, if you're trying to set the default value of the `Content` property from your custom control, you need to overwrite the `MetaData` for that property, like this:
// Note that this is the static constructor, not the normal one
static MyButton()
{
ContentProperty.OverrideMetadata(typeof(MyButton),
new FrameworkPropertyMetadata("756"));
}
This will make it so the default value of the `Content` property be `"756"` instead of `null`
Problem
I am using `OneWayToSource` binding and it seems that it always sets my source property to null. Why is that so? It's causing me troubles because I need value from the target property in my source property and not null. Here is my code: MyViewModel.cs: ``` public class MyViewModel { private string str; public string Txt { get { return this.str; } set { this.str = value; } } } ``` MainWindow.cs: ``` public MainWindow() { InitializeComponent(); MyViewModel vm = new MyViewModel(); vm.Txt = "123"; this.DataContext = vm; } ``` MainWindow.xaml: ``` <Window x:Class="OneWayToSourceTest.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525" xmlns:local="clr-namespace:OneWayToSourceTest"> <Grid> <local:MyButton Content="{Binding Path=Txt, Mode=OneWayToSource}"/> </Grid> </Window> ``` MyButton.cs: ``` public class MyButton : Button { public MyButton() { this.Content = "765"; } } ``` The target property is `MyButton.Content`. The source property is `MyViewModel.Txt`. The `Txt` property should be set to "765" but instead it is null. Why do I receive null instead 765? EDIT: Please take a look inside `MyButton` constructor. Actually If you would use simple `TwoWay` it will work. I tested it out and it has nothing to do with content being set inside constructor. Its something with `OneWayToSource` binding I guess. Now to explain how I used `TwoWay` binding, I did set the value of dp inside the constructor by calling `setvalue` method but then inside the wrapper or better said the getter and setter I didn't offer any setter hence why I made my `TwoWay` kinda look like its `OneWayToSource`. I did it to test out if its constructor fault. I figured the property inside viewmodel had the value 765 so that's what I meant with `TwoWay` binding. I just tested if it was control constructor. Its all fine with setting a value inside the constructor. By hiding setter I mean this set {}