2

How do XAML object initializers work with CLR properties?

If I need to create a XAML equivalent of :

public MainWindow()
{
    InitializeComponent();

    this.DataContext = new MainWindowViewModel();
}

then it would be :

<Window.DataContext>
    <vm:MainWindowViewModel/>
</Window.DataContext>

But if I want something like this:

public string KeyFieldView { get; set; }

public MainWindow()
{
    InitializeComponent();

    this.DataContext = new MainWindowViewModel()
    {
        KeyFieldVM=KeyFieldView
    };
}

I am able to get till, KeyFieldVM="", but not sure how do I access KeyFieldView.

<Window.DataContext>
    <vm:MainWindowViewModel KeyFieldVM=""/>
</Window.DataContext>
Manfred Radlwimmer
  • 13,257
  • 13
  • 53
  • 62
Simsons
  • 12,295
  • 42
  • 153
  • 269
  • 2
    This is why MS pisses me off so much. What you are asking for is trivial in XAML-2009, but WPF only supports the original version of XAML. – Jonathan Allen Feb 10 '17 at 10:35

2 Answers2

2

You can use the ObjectDataProvider as demonstrated in this answer to pass in constructor arguments to the instantiation of an object. However, these parameters can't be bound. Hence, your dynamic property value can't be used in the constructor.

You have to make those properties constants, and pass them in from your XAML, or fill them from the code behind.

Community
  • 1
  • 1
Patrick Hofman
  • 153,850
  • 22
  • 249
  • 325
2

You could bind the KeyFieldVM property provided that it is a dependency property:

public class MainWindowViewModel : DependencyObject
{
    public static readonly DependencyProperty KeyFieldVMProperty =
        DependencyProperty.Register("KeyFieldVM", typeof(string),
            typeof(MainWindowViewModel), new FrameworkPropertyMetadata("ok"));

    public string KeyFieldVM
    {
        get { return (string)GetValue(KeyFieldVMProperty); }
        set { SetValue(KeyFieldVMProperty, value); }
    }
}

<Window ... x:Name="win">
    <Window.DataContext>
        <vm:MainWindowViewModel KeyFieldVM="{Binding KeyFieldView, ElementName=win}"/>
    </Window.DataContext>
    <Grid>
        <TextBlock Text="{Binding KeyFieldVM}" />
    </Grid>
</Window>

This requires the view model to be a DependencyObject though and this has its drawbacks:

INotifyPropertyChanged vs. DependencyProperty in ViewModel

XAML is markup language. It doesn't have any concept of variables so you cannot do something like this:

<vm:MainWindowViewModel KeyFieldVM="{this.KeyFieldView}"/> <!-- BAD MARKUP -->

If you want to do this you should create the view model programmatically, for example in the code-behind of the view.

Community
  • 1
  • 1
mm8
  • 163,881
  • 10
  • 57
  • 88
  • Just though , I do not have to create a dependency property for accessing a normal CLR property, and could have avoided binding , but looks like thats the only way – Simsons Feb 10 '17 at 10:40
  • 1
    Any *target* property, i.e. the property that bind something *to* in the view, must be a dependency property. – mm8 Feb 10 '17 at 10:44