views:

405

answers:

1

The following code-behind binding works for the SmartFormView user control:

View:

<UserControl x:Class="CodeGenerator.Views.PageItemManageSettingsView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:v="clr-namespace:CodeGenerator.Views"
    xmlns:vm="clr-namespace:CodeGenerator.ViewModels"
    Background="#ddd">

    <Grid Margin="10">
        <ScrollViewer DockPanel.Dock="Top">
            <StackPanel Margin="10">
                <v:SmartFormView/>
            </StackPanel>
        </ScrollViewer>
    </Grid>

</UserControl>

code-behind:

using System.Windows.Controls;
using CodeGenerator.ViewModels;

namespace CodeGenerator.Views
{
    public partial class SmartFormView : UserControl
    {
        public SmartFormView()
        {
            InitializeComponent();
            DataContext = new SmartFormViewModel("testing");
        }
    }
}

However, I want to bind the SmartFormView to its SmartFormViewModel in the ViewModel of the calling View, not hard-coded in the code-behind. Yet these two approaches don't bind:

<UserControl.Resources>
<DataTemplate DataType="{x:Type vm:SmartFormViewModel}">
    <v:SmartFormView/>
</DataTemplate>
</UserControl.Resources>

...

<Grid Margin="10">
<ScrollViewer DockPanel.Dock="Top">

    <StackPanel Margin="10">

        <TextBlock Text="{Binding Testing}"/>

        <v:SmartFormView DataContext="{Binding SmartFormViewModel}"/>

        <ContentControl
            Content="{Binding SmartFormViewModel}"/>

    </StackPanel>

</ScrollViewer>
</Grid>

In the ViewModel I have "Testing" and "SmartFormViewModel" defined as ViewModel properties and fill them both (as shown below), but although the Testing property binds fine, the the SmartFormView does not bind to its SmartFormViewModel:

#region ViewModelProperty: SmartFormViewModel
private SmartFormViewModel _smartFormViewModel=;
public SmartFormViewModel SmartFormViewModel
{
    get
    {
        return _smartFormViewModel;
    }

    set
    {
        _smartFormViewModel = value;
        OnPropertyChanged("SmartFormViewModel");
    }
}
#endregion

#region ViewModelProperty: Testing
private string _testing;
public string Testing
{
    get
    {
        return _testing;
    }

    set
    {
        _testing = value;
        OnPropertyChanged("Testing");
    }
}
#endregion



public PageItemManageSettingsViewModel(MainViewModel mainViewModel, PageItem pageItem)
    : base(mainViewModel, pageItem)
{
    SmartFormViewModel SmartFormViewModel = new SmartFormViewModel("manageSettingsMain");
    Testing = "test ok";
}

What is the syntax to bind a UserControl in XAML to a specific ViewModel in the calling View's ViewModel?

+2  A: 

Could be wrong, but I think you just have a bug in your code.

SmartFormViewModel SmartFormViewModel = new SmartFormViewModel("manageSettingsMain");

Should be:

SmartFormViewModel = new SmartFormViewModel("manageSettingsMain");

ie. Your SmartFormViewModel is never being set. Therefore, the binding you have in your parent view doesn't find it.

Further to this, a better way to do this is just to stick your child VM into the visual tree:

<ContentControl Content="{Binding SmartFormViewModel}"/>

And use a DataTemplate to do the resolution of the view rather than "hard-coding" the view into the, um, parent view.

HTH, Kent

Kent Boogaart
yes that was it, thanks for finding that, nice to see, ok so I also tried your second way and that works well, too, and that makes more sense to me, so you seem to "define empty regions" which are then filled by ViewModels dynamically which automatically get bound to their appropriate DataTemplates upon rendering, makes sense, nice, thanks!
Edward Tanguay