Search code examples
c#wpfmvvmprismprism-6

Is Prism AutoWireViewModel compatible with MEF?


I am trying to combine AutoWireViewModel with MefBootstrapper to navigate between Views in various Modules. However I get an exception:

Set property 'Prism.Mvvm.ViewModelLocator.AutoWireViewModel' threw an exception

The exception points to this line of code: xmlns:prism="http://www.codeplex.com/prism"

XAML:

<UserControl x:Class="Login.Views.LoginForm"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:prism="http://www.codeplex.com/prism"
            prism:ViewModelLocator.AutoWireViewModel="True" Width="350">

    <Grid x:Name="LayoutRoot">
        <Grid.Background>
            <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                <GradientStop Color="#FF7B97D4" />
                <GradientStop Color="#FF244C8D" Offset="1" />
            </LinearGradientBrush>
        </Grid.Background>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="100" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />

        </Grid.RowDefinitions>

        <TextBlock Grid.Row="0" Text="Login" TextWrapping="Wrap" Grid.RowSpan="1" Grid.ColumnSpan="2" FontSize="18" Foreground="#FF2F3806" Margin="8,8,8,8" />

        <Label Grid.Row="1" Margin="10,10,10,10">username:</Label>
        <TextBox x:Name="txtUsername" Text="{Binding UserName}" Grid.Row="1" Grid.Column="1" Margin="10,10,10,10" VerticalContentAlignment="Center"></TextBox>
        <Label Grid.Row="2" Margin="10">password:</Label>
        <PasswordBox x:Name="txtPassword"  Grid.Row="2" Grid.Column="1" Margin="10,10,10,10" VerticalContentAlignment="Center" />
        <Button x:Name="btnLogin" Grid.Row="3" Grid.RowSpan="1" Grid.ColumnSpan="2" Margin="10,10,10,10" Content="Log In" FontWeight="Bold" />
        <TextBlock x:Name="txtMsg" Grid.Row="4"  Grid.RowSpan="1" Grid.ColumnSpan="2" Margin="10,10,10,10" />

    </Grid>

</UserControl>

View:

using System.ComponentModel.Composition;
using System.Windows.Controls;

namespace Login.Views
{
    [Export("LoginForm")]
    public partial class LoginForm : UserControl
    {

        public LoginForm()
        {
            InitializeComponent();
        }
    }
}

ViewModel:

using Prism.Mvvm;

namespace Login.ViewModels
{
    public class LoginFormViewModel : BindableBase
    {

        private string _username = "unamegoeshere";
        public string UserName
        {
            get { return _username; }
            set { SetProperty(ref _username, value); }
        }
    }
}

Shell:

[Export]
public partial class Shell : Window, IPartImportsSatisfiedNotification
{
    private const string InitialModuleName = "LoginModule";
    private static Uri InitialViewUri = new Uri("/LoginForm", UriKind.Relative);
    public Shell()
    {
        InitializeComponent();
    }

[Import(AllowRecomposition = false)]
public IModuleManager ModuleManager;

[Import(AllowRecomposition = false)]
public IRegionManager RegionManager;

public void OnImportsSatisfied()
{
    this.ModuleManager.LoadModuleCompleted +=
        (s, e) =>
        {
            if (e.ModuleInfo.ModuleName == InitialModuleName)
            {
                this.RegionManager.RequestNavigate(
                    RegionNames.MainContentRegion,
                    InitialViewUri);
            }
        };
}

Screenshot of error


Solution

  • The LoginFormViewModel needs the Export attribute.

     [Export]
     public class LoginFormViewModel ...
    

    And add the System.ComponentModel.Compositon namespace, too.