4
votes

I have a WPF app with 2 projects, one for the ViewModels (MyApp.Core) and another for the Views (MyApp).

Inside the Views and ViewModels I have different nested namespaces (for example: MyApp.Core.ViewModels.Example1).

I would like to register my Views and ViewModels in the App.xaml and use DataTemplates to bind ViewModels to Views.

What I currently have is this:

<Application
   x:Class="MyApp"
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   xmlns:example1v="clr-namespace:MyApp.Views.Example1"
   xmlns:example1vm="clr-namespace:MyApp.Core.ViewModels.Example1;assembly=MyApp.Core"
   xmlns:example2v="clr-namespace:MyApp.Views.Example1"
   xmlns:example2vm="clr-namespace:MyApp.Core.ViewModels.Example1;assembly=MyApp.Core"
   StartupUri="Views/MainWindow.xaml">

   <Application.Resources>
       <DataTemplate DataType="{x:Type example1vm:Example1ViewModel}">
           <example1v:Example1Window />
       </DataTemplate>
       <DataTemplate DataType="{x:Type example2vm:Example2ViewModel}">
           <example2v:Example2Window />
       </DataTemplate>
   </Application.Resources>
</Application>

As you can see, I have one namespace for every nested namespace and this will get bigger as the app grows.

My question is: Is there a way to import only the base namespace and then specify more in the XAMl tags?

I'm thinking of something like this:

<Application
   x:Class="MyApp"
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   xmlns:v="clr-namespace:MyApp.Views"
   xmlns:vm="clr-namespace:MyApp.Core.ViewModels;assembly=MyApp.Core"
   StartupUri="Views/MainWindow.xaml">

   <Application.Resources>
       <DataTemplate DataType="{x:Type vm:Example1.Example1ViewModel}">
           <v:Example1.Example1Window />
       </DataTemplate>
       <DataTemplate DataType="{x:Type vm:Example2.Example2ViewModel}">
           <v:Example2.Example2Window />
       </DataTemplate>
   </Application.Resources>
</Application>
1

1 Answers

3
votes

From x:Type Markup Extension:

<object property="{x:Type prefix:typeNameValue}" .../>

prefix Optional. A prefix that maps a non-default XAML namespace. Specifying a prefix is frequently not necessary. See Remarks.

typeNameValue Required. A type name resolvable to the current default XAML namespace; or the specified mapped prefix if prefix is supplied.

A quick test reveals that a compound name in typeNameValue actually just works - since it is obviously resolvable to the namespace prefix - although the XAML Designer may complain about a nested type not being supported.

namespace DataTypeNamespaceTest
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            DataContext = new Test.ViewModel();
        }
    }
}

namespace DataTypeNamespaceTest.Test
{
    public class ViewModel
    {
        public string Text { get; } = "Text in Test.ViewModel";
    }
}

XAML:

<Window x:Class="DataTypeNamespaceTest.MainWindow"
        xmlns:local="clr-namespace:DataTypeNamespaceTest"
        ...>
    <Window.Resources>
        <DataTemplate DataType="{x:Type local:Test.ViewModel}">
            <TextBlock Padding="10" Background="Aqua" Text="{Binding Text}"/>
        </DataTemplate>
    </Window.Resources>
    <Grid>
        <ContentControl Content="{Binding}"/>
    </Grid>
</Window>