Search code examples
wpfmvvmdatatemplate

Present UserControl.Resources


In my Xaml I have defined a resource as vehicleDataInput which presents some textboxes for user to input data. If I don't define a x:Key for it it will present itself in my app and works as it should. Problem is I want to decide were in my view it is placed with the help of a x:Key but I can't get the binding correct.

You can see in my code further down that I have tried with a content control and binding to "vehicleDataInput" but it does not work at runtime.

I have tried to find an answer to this problem but noone seems to have it which makes me think I`m aproaching this problem the wrong way, what have I missed?

<UserControl x:Class="RegCarManager.Vehicles.CreateVehicle.CreateVehicleView"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         xmlns:vehicles="clr-namespace:RegCarManager.Vehicles"
         xmlns:vehiclesViewModel="clr-namespace:RegCarManager.Vehicles.CreateVehicle"
         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="300">


<UserControl.Resources>
    <DataTemplate x:Key="vehicleDataInput" DataType="{x:Type vehicles:VehicleModel}">
        <Grid HorizontalAlignment="Stretch" VerticalAlignment="Top" >
            <Grid.ColumnDefinitions>
                <ColumnDefinition />
                <ColumnDefinition />
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition />
                <RowDefinition />
                <RowDefinition />
            </Grid.RowDefinitions>

            <TextBlock Grid.Column="0" Grid.Row="1" Text="Model" VerticalAlignment="Center" Margin="5" />
            <TextBox Grid.Column="1" Grid.Row="1" Text="{Binding Model}" Margin="5" Width="150" />

            <TextBlock Grid.Column="0" Grid.Row="2" Text="Reg number" VerticalAlignment="Center" Margin="5" />
            <TextBox Grid.Column="1" Grid.Row="2" Text="{Binding RegNumber}" Margin="5" Width="150" />
        </Grid>
    </DataTemplate>
</UserControl.Resources>


<DockPanel Margin="20">
    <ComboBox   DockPanel.Dock="Top"
                ItemsSource="{Binding Clients}" 
                DisplayMemberPath="FullName"
                SelectedValuePath="ClientId"
                SelectedValue="{Binding OwnerId, Mode=TwoWay}" />

    <ContentControl Content="{DynamicResource vehicleDataInput}" />

    <DockPanel DockPanel.Dock="Bottom">
        <Button Content="Save" DockPanel.Dock="Right" Margin="10,2" VerticalAlignment="Center"
                Command="{Binding Path=SaveNewVehicleCommand}" IsDefault="True" Width="100" />
    </DockPanel>

    <ContentControl Margin="20,10" Content="{Binding Path=NewVehicle}" />
</DockPanel>


Solution

  • A template is used to generate UI which displays content. It isn't the content; it's a description of how the content should be presented to the user.

    <ContentControl
        Content="{Binding NewVehicle}"
        ContentTemplate="{StaticResource vehicleDataInput}" 
        />
    

    I'm guessing that you must have an instance of VehicleModel somewhere in your main viewmodel. Is that what NewVehicle is?

    It doesn't really matter in this case whether you use StaticResource or DynamicResource. The difference is just that if you replace the vehicleDataInput resource in the resource dictionary with a different template at runtime, DynamicResource will be watching out for that and will update the ContentControl. But you won't be doing that, so StaticResource is fine.