Exception:the component does not have a resource identified by the uri

Exception:
Message: “组件“XXX”不具有由 URI“XXX”识别的资源。”
RemoteStackTrace: null
Source: “PresentationFramework”
StackTrace: 在 System.Windows.Application.LoadComponent(Object component, Uri resourceLocator)
在 myControl.InitializeComponent()
在 myControl..ctor()
TargetSite: {Void LoadComponent(System.Object, System.Uri)}
WatsonBuckets: null

查找源码,找到抛出异常的代码

    /// <summary>
    /// Create logic tree from given resource Locator, and associate this
    /// tree with the given component.
    /// </summary>
    /// <param name="component">Root Element</param>
    /// <param name="resourceLocator">Resource Locator</param>
    /// <SecurityNote>
    ///     Critical: This code calls critical method GetResourceOrContentStream to get part.
    ///     PublicOK: The part is not exposed.
    /// </SecurityNote>
    [SecurityCritical]
    public static void LoadComponent(Object component, Uri resourceLocator)
    {
        if (component == null)
            throw new ArgumentNullException("component");

        if (resourceLocator == null)
            throw new ArgumentNullException("resourceLocator");

        if (resourceLocator.OriginalString == null)
            throw new ArgumentException(SR.Get(SRID.ArgumentPropertyMustNotBeNull,"resourceLocator", "OriginalString"));

        if (resourceLocator.IsAbsoluteUri == true)
            throw new ArgumentException(SR.Get(SRID.AbsoluteUriNotAllowed));

        // Passed a relative Uri here.
        // needs to resolve it to Pack://Application.
        //..\..\ in the relative Uri will get stripped when creating the new Uri and resolving to the
        //PackAppBaseUri, i.e. only relative Uri within the appbase are created here
        Uri currentUri = new Uri(BaseUriHelper.PackAppBaseUri, resourceLocator);

        //
        // Generate the ParserContext from packUri
        //
        ParserContext pc = new ParserContext();

        pc.BaseUri = currentUri;

        bool bCloseStream = true;  // Whether or not to close the stream after LoadBaml is done.

        Stream stream = null;  // stream could be extracted from the manifest resource or cached in the
                               // LoadBamlSyncInfo depends on how this method is called.

        //
        // We could be here because of an InitializeCompoenent() call from the ctor of this component.
        // Check if this component was originally being created from the same Uri by the BamlConverter
        // or LoadComponent(uri).
        //
        if (IsComponentBeingLoadedFromOuterLoadBaml(currentUri) == true)
        {
            NestedBamlLoadInfo nestedBamlLoadInfo = s_NestedBamlLoadInfo.Peek();

            // If so, use the stream already created for this component on this thread by the
            // BamlConverter and seek to origin. This gives better perf by avoiding a duplicate
            // WebRequest.
            stream = nestedBamlLoadInfo.BamlStream;

            stream.Seek(0, SeekOrigin.Begin);

            pc.SkipJournaledProperties = nestedBamlLoadInfo.SkipJournaledProperties;

            // Reset the OuterUri in the top LoadBamlSyncInfo in the stack for the performance optimization.
            nestedBamlLoadInfo.BamlUri = null;

            // Start a new load context for this component to allow it to initialize normally via
            // its InitializeComponent() so that code in the ctor following it can access the content.
            // This call will not close the stream since it is owned by the load context created by
            // the BamlConverter and will be closed from that context after this function returns.

            bCloseStream = false;
        }
        else
        {
            // if not, this is a first time regular load of the component.
            PackagePart part = GetResourceOrContentPart(resourceLocator);
            ContentType contentType = new ContentType(part.ContentType);
            stream = part.GetStream();
            bCloseStream = true;

            //
            // The stream must be a BAML stream.
            // check the content type.
            //
            if (!MimeTypeMapper.BamlMime.AreTypeAndSubTypeEqual(contentType))
            {
                throw new Exception(SR.Get(SRID.ContentTypeNotSupported, contentType));
            }
        }

        IStreamInfo bamlStream = stream as IStreamInfo;

        if (bamlStream == null || bamlStream.Assembly != component.GetType().Assembly)
        {
            throw new Exception(SR.Get(SRID.UriNotMatchWithRootType, component.GetType( ), resourceLocator));
        }

        XamlReader.LoadBaml(stream, pc, component, bCloseStream);
    }

异常的地方

        if (bamlStream == null || bamlStream.Assembly != component.GetType().Assembly)
        {
            throw new Exception(SR.Get(SRID.UriNotMatchWithRootType, component.GetType( ), resourceLocator));
        }

网友的回答:

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…

得出结论:
uri指向的xaml所在的Assembly 与 组件所在的Assembly不是同一个。所以抛出异常。
返回到项目确实如此mycontrol存在与两个地方,调用的地方及启动的地方。

引用

点赞