MVVMLight within another MVVMLight project

2019-08-24 02:49发布

问题:

I am working on a MVVMLight / WPF project and need to add a chunk of functionality which will include multiple views and viewmodels. I know this same bit of functionality will be used in other projects in the near future so I would like to make this functionality its own project that I can add to other solutions as needed wiuth little or no modification.

I started by adding a second MVVMLight project (Beta), removing the standard MainWindow.xaml and MainViewModel.cs files and created a simple UserControl and associated View Model.

<UserControl x:Class="Beta.View.TestView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:ignore="http://www.ignore.com"
        mc:Ignorable="d ignore"
        DataContext="{Binding Test_VM, Source={StaticResource Locator} }">

    <Grid>
        <TextBlock Text="{Binding WelcomeMessage}" />
    </Grid>
</UserControl>



public class TestViewModel : ViewModelBase
{
    #region Properties

    public string WelcomeMessage
    {
        get
        {
            return "Hello World!";
        }
    }

    #endregion Properties

    #region Constructors

    /// <summary>
    /// Initializes a new instance of the TestViewModel class.
    /// </summary>
    public TestViewModel()
    {

    }

    #endregion Constructors
}

I am able to add Beta as a reference to the original project (Alpha) and display the view by inserting the view into a stack panel like so:

<StackPanel Name="MasterStackPanel"
            DockPanel.Dock="Top">
    <beta:TestView />
</StackPanel>

Everything appears to work properly when doing this. The issue I am having is when I try to bind a Property from TestViewModel to TestView.

In TestView, if I do this:

<TextBlock Text="Hello World" />

the TestView displays correctly at runtime. But when I bind the TextBlock to a property like so:

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

The message does not display and the locator for Beta appears to be ignored (the datacontext is not being bound) and I am getting the following error from Snoop:

System.Windows.Data Error: 40 : BindingExpression path error: 'WelcomeMessage' property not found on 'object' ''MainViewModel' (HashCode=51013215)'. BindingExpression:Path=WelcomeMessage; DataItem='MainViewModel' (HashCode=51013215); target element is 'TextBlock' (Name=''); target property is 'Text' (type 'String')
System.Windows.Data Error: 40 : BindingExpression path error: 'Test_VM' property not found on 'object' ''ViewModelLocator' (HashCode=22749765)'. BindingExpression:Path=Test_VM; DataItem='ViewModelLocator' (HashCode=22749765); target element is 'TestView' (Name=''); target property is 'DataContext' (type 'Object')

I believe this means that the binding of Test_VM & WelcomeMessage are trying to be found via the Alpha Locator and not the Beta Locator. I am using the ViewModelLocator that is created by default when starting a MVVMLight project in each project.

Is it possible to have an second 'Locator' and if so what do I need to do to make it work?

回答1:

I think you should only have one Locator in the application root of the system and use the "MvvmLightLibs" library in the library project and reference it in the alpha project and add a TestViewModel-Property in the locator.