简体   繁体   中英

How do I use Dependency Injection between a Core project and a WPF application with changing pages?

I am building a WPF program using the MVVM Framework, along with Ninject for Dependancy Injection . I have created two projects, a .Net Class Library Core project for use with other .Net Applications and a WPF specific application.

Currently I am changing pages with my application using an ApplicationViewModel with a Property CurrentPage . CurrentPage is an Enum type called ApplicationPage containing the different pages within my application. Within the MainWindow of my WPF application is a frame whose Content is bound to the CurrentPage Property and uses a value converter to convert the value to different CustomPages I have made using a switch statment, like so:

if (value is ApplicationPage)
    switch ((ApplicationPage)value)
    {
        case ApplicationPage.PageOne:
            return new PageOne();
        case ApplicationPage.PageTwo:
            return new PageTwo();
        default:
            throw Exception;
    }
}

I would like to use Constructor Injection to pass the View Models for these pages into a Page's Constructor within the Converter , Using ViewModels that have in turn been Injected into the ApplicationViewModel class, kind of like so:

case ApplicationPage.PageOne:
    return new PageOne(PageOneViewModel);

My first thought was, is there some way of making the CurrentPage Property actually a specific ViewModel and perform a switch on which ViewModel so the Converter converts a ViewModel to a Page ?

However the Type of CurrentPage is an issue as it has to be set to one of the ViewModels and therefore cannot take the value of a different ViewModel , leaving you stuck with only one ViewModel Class to work with.

My thoughts are: Is there a way to pass in the ViewModel to the Converter ? Or Could I set CurrentPage to an IViewModelFactory and Create the ViewModel within the converter from the Factory? In which case how would I change the value of CurrentPage in order to change the page in the application?

Is there a way to stick to Dependency Injection while following this logic, or is there another way and do I need to rethink my code for page changing? Unfortunately most examples I have seen have fallen into the so called ServiceLocator anti-pattern.

The answer is to use data templates as follows,

<Window.Resources>
    <DataTemplate x:Key="View1Template" DataType="{x:Type local:MainWindowViewModel}">
        <!-- Custom control style with a Data Context set to a Viewmodel 
        object in the MainWindowViewModel -->
        <local:CustomPage1 DataContext="{Binding CustomPage1ViewModel}" />
    </DataTemplate>

    <DataTemplate x:Key="View2Template" DataType="{x:Type local:MainWindowViewModel}">
        <!-- Custom control style with a Data Context set to a Viewmodel 
        object in the MainWindowViewModel -->
        <local:CustomPage2 DataContext="{Binding CustomPage2ViewModel}" />
    </DataTemplate>
</Window.Resources>

Then setting a Data Trigger within the Content Control Style ;

<ContentControl Content="{Binding}">
    <ContentControl.Style>
        <Style TargetType="{x:Type ContentControl}">

            <!-- The Default/initial View being shown -->
            <Setter Property="ContentTemplate" Value="{StaticResource View1Template}" />

            <!-- Triggers bound to the CurrentView Property -->
            <Style.Triggers>
                <DataTrigger Binding="{Binding CurrentView}" Value="1">
                    <Setter Property="ContentTemplate" Value="{StaticResource View1Template}" />
                </DataTrigger>
                <DataTrigger Binding="{Binding CurrentView}" Value="2">
                    <Setter Property="ContentTemplate" Value="{StaticResource View2Template}" />
                </DataTrigger>
            </Style.Triggers>

        </Style>
    </ContentControl.Style>
</ContentControl>

The CurrentView is a property that can be changed in code to Trigger a change in the UI - can be set to an Enum of PageNames .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM