c# - El componente no tiene un recurso identificado por el uri
.net wpf (16)
Quiero crear un DataGrid Genérico para usar en todas mis Vistas / UserControls.
Esta es mi estructura:
Class Library
llamada "Core"
:
Class
llamada "ViewBase"
:
public class ViewBase : UserControl
{
public ViewBase()
{
}
//Rest of Methods and Properties
}
Class Library
llamada "Controls"
:
UserControl
llamado "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>
Código detrás:
using Core;
public partial class GridView : ViewBase
{
public GridView ()
{
InitializeComponent();
}
}
Entonces es la aplicación WPF llamada "WPFApp":
Class
llamada "View"
:
using Controls;
public class View : GridView
{
public View()
{
InitializeComponent();
}
}
Mi idea es usar GridView
donde necesito un DataGrid
.
Cuando ejecuto la aplicación obtengo este error:
"The component ''WpfApp.View'' does not have a resource identified by the URI ''/Controls;component/GridView.xaml''."
¿Qué estoy haciendo mal?
¿Es este el enfoque correcto o estoy lejos?
¡Esto me dio dolores de cabeza durante 3 días! Tengo un UserControl XAML en una biblioteca de clase y una clase (solo C #) que se deriva del UserControl en mi proyecto .exe. En el diseñador xaml de mi MainWindow.xaml y al iniciar la aplicación, recibí el error "el componente no tiene un recurso identificado por el uri". La respuesta de "Juan Carlos Girón" finalmente me llevó a la solución:
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
}
}
}
}
y lo llamó desde el archivo .cs de UserControl:
namespace ClassLibrary1
{
public partial class MyUserControl : UserControl
{
public MyUserControl()
{
//InitializeComponent();
this.LoadViewFromUri("/ClassLibrary1;component/myusercontrol.xaml");
}
}
}
¡Gracias de nuevo a "Juan Carlos Girón"!
@Willem, esto me parece perfectamente bien. De hecho, probé esto y funcionó en mi caso. ListBox
lugar de DataGrid
(pero eso no debería importar).
Todos mis espacios de nombres estaban en una asamblea. Así que utilicé un espacio de nombres padre común para todos, por ejemplo
MyWpfApplication.Controls
MyWpfApplciation.GridView
MyWpfApplciation.ViewBase
Debido a que todos estos Controls
, GridView
, ViewBase
están en conflicto con el espacio de nombres y las declaraciones de clase basados en System
o System.Windows.Controls
. Así que me aseguré de MyWpfApplication.*
las MyWpfApplication.*
correctas MyWpfApplication.*
En mi proyecto.
Accidentalmente borré un control de usuario mediante una acción de cambio de nombre / copia . Cuando reinstalé el archivo de proyecto y el archivo xaml y .cs desde el control de la versión, este error comenzó a suceder en el estudio de diseño para ese control que se había eliminado / renombrado por error.
Eso sugirió algún tipo de caché en el archivo en cuestión ... así que cerrar Visual Studio, eliminar el directorio bin
y reconstruir funcionó.
El mismo problema aqui.
Version corta:
Copy Local tiene que establecerse en False !
Versión larga:
Desarrollamos una solución WPF (MVVM, 20 proyectos) e implementamos un sistema de plug-in. Nuestro directorio / bin / Debug contiene el ejecutable, algunos archivos dll y un directorio de complementos que contiene los complementos. Hay un proyecto "DialogLib" (biblioteca de clases, tipo de diálogo) que define una ventana (la vista), el modelo de vista, el modelo y algunas interfaces. Uno de los complementos usaba una de las interfaces de DialogLib. La ventana en sí es abierta por la aplicación principal.
Para usar la interfaz de la biblioteca ''DialogLib'' en el complemento, tuvimos que agregar una referencia de proyecto de DialogLib a las referencias del proyecto de complementos. Cuando se inició la aplicación, se cargaron los complementos. Si el usuario luego selecciona un elemento de menú, la ventana debería abrirse. En este punto, el error "... componente no tiene un recurso identificado por el URI ..." se produjo cuando el código de Windows detrás intentó ejecutar su InitializeComponent ().
¿Dónde está el problema?
El problema es que, cuando creamos la solución, VS creó DialogLib.dll correctamente y lo copió en / bin / Debug /. Esto se debe a que el archivo principal de la aplicación desea abrir la ventana. Pero DialogLib.dll también se copió en / bin / Debug / plugins porque uno de los complementos lo referenciaba para usar una de las interfaces definidas en DialogLib.dll. ¿Y qué?
Cuando el complemento se carga en tiempo de ejecución, utiliza la interfaz definida en /bin/Debug/plugins/DialogLib.dll. y el archivo principal de la aplicación intenta abrir la ventana definida en /bin/Debug/DialogLib.dll. Aunque los archivos son idénticos, VS tiene problemas. Establecer el valor de Copiar local de las propiedades de referencia de DialogLib de las referencias de complementos evita copiar DialogLib.dll en / bin / Debug / plugins y así resolver el problema.
Tuvimos un problema similar (pero diferente) en otro proyecto en el que queríamos usar un tipo TypeA , que se definió en un archivo dll, en un complemento y en la aplicación principal. Copy Local se configuró en true, lo que provocó que una copia del archivo dll se ubicara en ../bin/Debug/plugins y en ../bin/Debug/ . Resultó que, aunque era el mismo archivo dll, TypeA en el archivo principal de la aplicación y TypeA en el complemento se trataban como tipos diferentes, respectivamente, como tipos que no se podían intercambiar.
El motivo por el que recibe este error es porque la forma en que InitializeComponent se implementa (en VS 2010) siempre buscará en el ensamblado de la clase derivada.
Aquí está 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
}
La línea donde busca su recurso XAML es System.Windows.Application.LoadComponent (this, resourceLocator). Y esto probablemente falle porque el equivalente de ''this.GetType (). Assembly'' se usa para determinar qué ensamblaje buscará el recurso identificado por el Uri relativo. Y ''this.GetType ()'' obtiene el tipo derivado del objeto, no el tipo de la clase donde se implementa el código.
PD. ¿Es esto un error? No lo sé...
Estaba haciendo algo muy similar con el mismo resultado. Tenía una biblioteca de clase C # que contenía un control WPF llamado UsageControl (xaml con el archivo xaml.cs adjunto). En un proyecto separado de C # (es decir, dll por separado) creé una clase C # CPUUsageControl que heredó de UsageControl, pero le di su propio giro. Cuando intenté usar CpuUsageControl en una de mis vistas, recibí el mismo error que tú.
Lo que hice para arreglar eso fue en mi ensamblado separado, en lugar de crear una clase heredada del control base, creé un nuevo Control WPF que contenía el control base. Luego coloqué toda la lógica contenida en la clase CpuUsage en el código de WpfCpuUsageControl. Pude usar este objeto, todos mis otros controles están bien.
Para su Control "GridView" crearía un nuevo control de usuario WPF , llámelo GridView y haga que contenga una "ViewBase" como el contenido del control Grid. Dentro del contenido ViewBase coloque en su DataGrid, así:
<UserControl....>
<Grid>
<ViewBase name="vBase">
<DataGrid name="dGrid" />
</ViewBase>
</Grid>
</UserControl>
Tampoco es evidente para mí que necesite que ViewBase herede UserControl directamente. Si todo lo que quiere es que sus controles tengan ciertas propiedades y métodos, por qué no solo crea una clase BaseControl (que no hereda de nadie sino de objetos) y tiene controles futuros heredados de ella. Quizás una clase base o interfaz abstracta es lo que buscas.
Para los proyectos MVVM WPF, normalmente tengo un modelo BaseView que implementa INotifyPropertyChanged para mí, así que no tengo que hacer el mismo código en todas partes.
La mejor de las suertes, sé que este problema fue un gran dolor de entender. ¡El mensaje de excepción y google son inútiles!
Esto también puede suceder al cerrar y volver a abrir una ventana. Por lo tanto, tampoco podría tener nada que ver con paquetes y / o dlls.
Resolví el problema gracias a la solución publicada por PainElemental, que en mi humilde opinión está subestimada:
namespace MyNamespace
{
public partial class MyDialog : Window
{
public MyDialog(ExcelReference sheetReference)
{
this.LoadViewFromUri("/MyApp;component/mynamespace/mydialog.xaml");
}
}
}
LoadViewFromUri se implementa como una extensión, como escribió PainElemental. Lo más loco es que también escribí en el mismo proyecto otras ventanas sin encontrar ningún problema.
Gracias PainElemental, ¡terminaste mi dolor prolongado!
Frustrante, tuve exactamente este error y pasé para siempre tratando de resolver la causa. Para mí, una vez estuvo funcionando, pero luego hice algunos cambios menores en el XAML del control derivado, y el compilador comenzó a dar ese mensaje de error. Solución corta, eliminando muchas horas de tratar de resolverlo: cerrar Visual Studio y volver a abrirlo, recompilarlo, el problema desapareció mágicamente. (Esto es VS2012 Pro) Acabo de agregar esto en caso de que alguien lea dando vueltas en círculos tratando de encontrar un problema inexistente con su código. Podría valer la pena probar primero la "solución IT Crowd".
Más rápido que cerrar todo Visual Studio es simplemente matar XDescProc.exe en su administrador de tareas.
XDescProc es el diseñador. En el momento en que se cierre el proceso, verá un enlace Volver a cargar el diseñador en Visual Studio. Haga clic en eso y XDes se iniciará nuevamente y su error ''sin recursos'' debería desaparecer.
Aquí está el enlace visual studio muestra después de matar el proceso de diseñador:
Me encontré con este problema también sin ningún problema de herencia. Solo estaba haciendo referencia a una DLL que contenía un diálogo e intentaba crear y mostrar ese diálogo. Tengo ensamblador de resolución que carga ensamblajes desde una carpeta específica y resulta que había agregado la referencia en VS y no había desactivado Copiar local. Para resumir: mi proceso había cargado dos versiones de esa misma DLL. Esto parece confundir WPF (o el tiempo de ejecución). Una vez que eliminé Copy Local y eliminé las copias adicionales de DLL, funcionó bien de nuevo.
Me sucedió cuando tuve el mismo proyecto abierto en dos soluciones. Modificar el control base en un proyecto causa que el otro proyecto tenga este problema. Si cerrar y abrir no funciona, elimine todas las carpetas en "C: / Users ... / AppData / Local / Microsoft / VisualStudio / 12.0 / Designer / ShadowCache"
Puedes probar este enfoque
Creé mi propio InitializeComponent()
y llamé de esta manera
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
}
}
Recibí el mismo error cuando uso Visual Studio 2013.
El componente no tiene un recurso identificado por el uri
Intentó:
Limpiar y reconstruir la solución, no funcionó.
Cerrar y abrir Visual Studio - no funcionó.
Solución:
Ingresé al directorio bin
proyectos y borró todos los archivos.
Corrió el proyecto nuevamente y funcionó bien.
Abra la consola de Package Manager que se abrirá en el directorio raíz de su solución y ejecute el siguiente comando de PowerShell:
Get-ChildItem -inc bin,obj -recurse | Remove-Item -recurse -force -EA SilentlyContinue
Recibí este error después de cambiar el nombre de un archivo xaml. Invertir el cambio de nombre resolvió el problema.
Además, descubrí que no se actualizó una referencia al nombre del archivo xaml en App.xaml (StartupUri), pero cambiarle el nombre al nombre actual no resolvió el problema (pero tal vez lo haga por usted). Básicamente, no puedo cambiar el nombre del archivo xaml.
Fyi, para mí, el componente ''quejarse'' en el error fue SplitComboBox.
Resolví esto colocando
myusercontrol = Activator.CreateInstance<myusercontrol>();
en el constructor de la ventana que contiene usercontrol antes del InitializeComponent();
línea
- Eliminar carpeta
obj
- Eliminar carpeta
bin
- Reconstruir la solución
¡Trabajó para mi!
Además, si está cargando ensamblajes usando Assembly.LoadFile
, consulte AppDomain.CurrentDomain.GetAssemblies()
para ensamblajes duplicados en el AppDomain actual. Debido a que en el código autogenerado de WPF UserControl, el componente se cargará utilizando su URI relativo. Y dado que hay conjuntos duplicados en el AppDomain actual, la aplicación no sabe cuál usar.