Cannot find resource named 'ViewModelLocator&#

2019-08-04 15:42发布

问题:

I am trying to use ViewModelLocator by declaring it as a resource in App.xaml. Its a very simple class as follows:

public class ViewModelLocator
    {
        public ShellViewModel ShellPage
        {
            get
            {
                return new ShellViewModel();
            }
        }
}

App.xaml file is as below:

<Application x:Class="SomeNamespace.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:vm="clr-namespace:SomeNamespace.ViewModels">
    <Application.Resources>
         <vm:ViewModelLocator x:Key="ViewModelLocator" />
    </Application.Resources>
</Application>

App.xaml.cs is as below:

public partial class App : Application
    {
        protected override void OnStartup(StartupEventArgs e)
        {
            base.OnStartup(e);

            var view = new ShellView();
            Current.MainWindow = view;
            Current.MainWindow.Show();            
        }
    }

ShellView.xaml is a below:

<Window 
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        x:Class="SomeNamespace.ShellView"
        Title="MainWindow" 
        Height="350" 
        Width="525" 
        ResizeMode="NoResize" 
        MinWidth="700" 
        MinHeight="700"
        DataContext="{Binding ShellPage, Source={StaticResource ViewModelLocator}}"
        >
    <Grid>
        <TextBlock Text="{Binding Title}"></TextBlock>
    </Grid>
</Window>

I can see the correct title in Visual Studio designer but when i run the app, get XamlParseException: 'Provide value on 'System.Windows.StaticResourceExtension' threw an exception.' Line number '11' and line position '9'.

The innerexception has {"Cannot find resource named 'ViewModelLocator'. Resource names are case sensitive."}

Am i missing something ?

回答1:

Try putting it inside a ResourceDictionary

<Application.Resources>
    <ResourceDictionary>
        <vm:ViewModelLocator x:Key="ViewModelLocator" />
    </ResourceDictionary>
</Application.Resources>

Edit:

I solved the problem by using the Startup event in the App, instead of overriding OnStartup.

<Application x:Class="TestWPF.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:vm="clr-namespace:TestWPF.ViewModels"
             Startup="App_Startup">
    <Application.Resources>
          <vm:ViewModelLocator x:Key="ViewModelLocator" />
    </Application.Resources>
</Application>

Code

public partial class App : Application
{
    void App_Startup(object sender, StartupEventArgs e)
    {
        var view = new ShellView();
        Current.MainWindow = view;
        Current.MainWindow.Show();
    }
}


回答2:

At startup time you're loading the window, this is not a good practice in my opinion because the resources are not yet entirely resolved in both App in witch your Window depends. Even if you're seeing properties loading at design time this is not always a good argument, though design is following another logic to execute the code.
You have to let App and Windows load and then fill the context property in the Window's grid


Remove the resource XAML from App.xaml (it looks really out of the scope there) and do this instead :

 <Window.Resources>
        <wpfApplication1:ViewModelLocator x:Key="ViewModelLocator" />
    </Window.Resources>

    <Grid   DataContext="{Binding ShellPage, Source={StaticResource ViewModelLocator}}">
        <TextBlock Text="{Binding Title}"></TextBlock>
    </Grid>


回答3:

It seems i found a solution.The reason maybe the StartUrl in the App.xaml.

1.Remove the default StartUrl in the App.xaml.Such like this:

        <Application x:Class="BidingAccessories.App" 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" d1p1:Ignorable="d"
                     xmlns:d1p1="http://schemas.openxmlformats.org/markup-compatibility/2006">
            <Application.Resources>
                <ResourceDictionary>
                    <vm:ViewModelLocator x:Key="Locator" xmlns:vm="clr-namespace:BidingAccessories.ViewModel" />
                    <ResourceDictionary.MergedDictionaries>
                        <ResourceDictionary Source="pack://application:,,,/BidingCommon;component/CommonStyleDictionary.xaml" />
                    </ResourceDictionary.MergedDictionaries>
                </ResourceDictionary>
            </Application.Resources>
        </Application>
        </Application.Resources>
        </Application>

2. override the OnstartUp event in App.xaml.cs

    protected override void OnStartup(StartupEventArgs e)
        {
            StartupUri = new Uri("MainWindow.xaml", UriKind.Relative);
    }