The component does not have a resource identified by the uri

37,591

Solution 1

I was doing something very similar with the same result. I had one C# class library that contained a WPF control called UsageControl (xaml with accompanying xaml.cs file). In a separate C# project(i.e. separate dll) I created a C# class CPUUsageControl which inherited from UsageControl, but put its own spin on it. When I tried to use the CpuUsageControl on one of my views I got the same error you did.

What I did to fix that was in my seperate assembly, instead of creating a class that inherited from the base control, i created a new WPF Control that contained the base control. I then put all of the logic that was contained in the CpuUsage class into the WpfCpuUsageControl's code behind. I was able to use this object is all of my other controls just fine.

For your Control "GridView" i would create a new WPF user control, call it GridView and make it contain a "ViewBase" as the content of the Grid control.Inside of the ViewBase's content put in your DataGrid, like this:

<UserControl....>
    <Grid>
        <ViewBase name="vBase">
            <DataGrid name="dGrid" />
        </ViewBase>
    </Grid>
</UserControl>

It is also not apparent to me that you need ViewBase to inherit from UserControl directly. If all you want are for your controls to have certain properties and method why not just make a BaseControl class (that does not inherit from anyone but object) and have future controls inherit from it. Perhaps an abstract base class or interface is what you're after.

For MVVM WPF projects, I typically have a BaseViewModel which implements INotifyPropertyChanged for me so I don't have to do that same code everywhere.

Best of luck, I know this problem was a huge pain to figure out. The exception message and google are most unhelpful!

Solution 2

Frustratingly, I had exactly this error and spent forever trying to work out the cause. For me, it was once working but then I made some very minor changes to the XAML of the derived control, and the compiler started giving that error message. Short solution, cutting out many hours of trying to figure it out: shut down Visual Studio and re-opened it, recompiled, problem magically went away! (This is VS2012 Pro) Just added this in case anyone reading is going round in circles trying to find a non-existent problem with their code. Might be worth trying the "IT Crowd solution" first.

Solution 3

This gave me headaches for 3 days! I have a XAML UserControl in a class library and a class (only C#) that derives from the UserControl in my .exe project. In xaml designer of my MainWindow.xaml and when starting the application, I got the error "component does not have a resource identified by the uri". The answer of "Juan Carlos Girón" finally lead me to the solution:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;
using System.Reflection;
using System.IO.Packaging;
using System.Windows.Markup;

namespace ClassLibrary1
{
    static class Extension
    {
        public static void LoadViewFromUri(this UserControl userControl, string baseUri)
        {
            try
            {
                var resourceLocater = new Uri(baseUri, UriKind.Relative);
                var exprCa = (PackagePart)typeof(Application).GetMethod("GetResourceOrContentPart", BindingFlags.NonPublic | BindingFlags.Static).Invoke(null, new object[] { resourceLocater });
                var stream = exprCa.GetStream();
                var uri = new Uri((Uri)typeof(BaseUriHelper).GetProperty("PackAppBaseUri", BindingFlags.Static | BindingFlags.NonPublic).GetValue(null, null), resourceLocater);
                var parserContext = new ParserContext
                {
                    BaseUri = uri
                };
                typeof(XamlReader).GetMethod("LoadBaml", BindingFlags.NonPublic | BindingFlags.Static).Invoke(null, new object[] { stream, parserContext, userControl, true });
            }
            catch (Exception)
            {
                //log
            }
        }
    }
}

and called that from by UserControl's .cs file:

namespace ClassLibrary1
{
    public partial class MyUserControl : UserControl
    {
        public MyUserControl()
        {
            //InitializeComponent();
            this.LoadViewFromUri("/ClassLibrary1;component/myusercontrol.xaml");
        }
    }
}

Thanks again to "Juan Carlos Girón"!

Solution 4

The reason you are getting this error is because the way InitializeComponent that is implemented (in VS 2010) will always search in the derived class's assembly.

Here is InitializeComponent:

/// <summary>
/// InitializeComponent
/// </summary>
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "4.0.0.0")]
public void InitializeComponent() {
    if (_contentLoaded) {
        return;
    }
    _contentLoaded = true;
    System.Uri resourceLocater = new System.Uri("/WpfApplication1;component/mainwindow.xaml", System.UriKind.Relative);

    #line 1 "..\..\..\MainWindow.xaml"
    System.Windows.Application.LoadComponent(this, resourceLocater);

    #line default
    #line hidden
}

The line where it looks up your XAML resource is System.Windows.Application.LoadComponent(this, resourceLocator). And this most probably fails because equivalent of 'this.GetType().Assembly' is used to determine which assembly to search for the resource identified by the relative Uri. And 'this.GetType()' does get the derived type of the object, not the type of the class where the code is implemented.

PS. Is this a bug? I do not know...

Solution 5

You can try this approach

I created my own InitializeComponent() and I called this way

this.LoadViewFromUri("/NameOfProject;component/mainwindow.xaml");


public static void LoadViewFromUri(this Window window, string baseUri)
    {
        try
        {
            var resourceLocater = new Uri(baseUri, UriKind.Relative);
            var exprCa = (PackagePart)typeof(Application).GetMethod("GetResourceOrContentPart", BindingFlags.NonPublic | BindingFlags.Static).Invoke(null, new object[] { resourceLocater });
            var stream = exprCa.GetStream();
            var uri = new Uri((Uri)typeof(BaseUriHelper).GetProperty("PackAppBaseUri", BindingFlags.Static | BindingFlags.NonPublic).GetValue(null, null), resourceLocater);
            var parserContext = new ParserContext
            {
                BaseUri = uri
            };
            typeof(XamlReader).GetMethod("LoadBaml", BindingFlags.NonPublic | BindingFlags.Static).Invoke(null, new object[] { stream, parserContext, window, true });

        }
        catch (Exception)
        {
            //log
        }
    }
Share:
37,591
Willem
Author by

Willem

.net Fan Love wpf MVVM + M

Updated on July 09, 2022

Comments

  • Willem
    Willem almost 2 years

    I want to create a Generic DataGrid to use on all my Views/UserControls.

    This is my structure:

    Class Library called "Core":

    Class called "ViewBase":

    public class ViewBase : UserControl
    {
        public ViewBase()
        {
        }   
    
        //Rest of Methods and Properties
    }
    

    Class Library called "Controls":

    UserControl Called "GridView":

    XAML:

        <vb:ViewBase x:Class="Controls.GridView"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
                 xmlns:vb="clr-namespace:Core;assembly=Core">
    
        <Grid>
            <DataGrid></DataGrid>
        </Grid>
    
        </vb:ViewBase>
    

    Code Behind:

    using Core;
    
    public partial class GridView : ViewBase
    {
        public GridView ()
        {
            InitializeComponent();
        }
    }
    

    Then is the WPF Aplication called "WPFApp":

    Class called "View":

    using Controls;
    
    public class View : GridView
    {
        public View()
        {
            InitializeComponent();
        }
    }
    

    My whole idea is to use GridView where i need a DataGrid.

    When i run the application i get this error:

    "The component 'WpfApp.View' does not have a resource identified by the URI '/Controls;component/GridView.xaml'."
    

    What am i doing wrong?

    Is this the correct approach or am i way off?