У компонента нет ресурса, идентифицированного uri
Я хочу создать общий DataGrid для использования во всех моих представлениях /UserControls.
Это моя структура:
Class Library
называется "Core"
:
Class
называется "ViewBase"
:
public class ViewBase : UserControl
{
public ViewBase()
{
}
//Rest of Methods and Properties
}
Class Library
называется "Controls"
:
UserControl
Вызывается "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>
Код за:
using Core;
public partial class GridView : ViewBase
{
public GridView ()
{
InitializeComponent();
}
}
Затем это приложение WPF, называемое "WPFApp":
Class
называется "View"
:
using Controls;
public class View : GridView
{
public View()
{
InitializeComponent();
}
}
Вся моя идея - использовать GridView
, где мне нужен DataGrid
.
Когда я запускаю приложение, я получаю эту ошибку:
"The component 'WpfApp.View' does not have a resource identified by the URI '/Controls;component/GridView.xaml'."
Что я делаю неправильно?
Является ли это правильным подходом или нет?
Ответы
Ответ 1
Я делал что-то очень похожее с тем же результатом. У меня была одна библиотека классов С#, содержащая элемент управления WPF, называемый UsageControl (xaml с сопровождающим файлом xaml.cs). В отдельном проекте С# (например, отдельная dll) я создал С# class CPUUsageControl, который унаследовал из UsageControl, но поместил его на него. Когда я попытался использовать CpuUsageControl в одном из своих представлений, я получил ту же ошибку, что и вы.
Что я сделал, чтобы исправить это в моей отдельной сборке, вместо создания класса, унаследованного от базового элемента управления, я создал новый элемент управления WPF, в котором содержится базовый элемент управления. Затем я поместил всю логику, содержащуюся в классе CpuUsage, в код WpfCpuUsageControl. Я смог использовать этот объект, все мои другие элементы управления просто прекрасны.
Для вашего элемента управления "GridView" я создам новый пользовательский элемент управления WPF, вызовите его GridView и сделайте его содержать a "ViewBase" в качестве содержимого элемента управления сеткой. Помимо содержимого ViewBase, помещенного в ваш DataGrid, выполните следующие действия:
<UserControl....>
<Grid>
<ViewBase name="vBase">
<DataGrid name="dGrid" />
</ViewBase>
</Grid>
</UserControl>
Мне также не кажется, что вам нужно, чтобы ViewBase напрямую наследовался от UserControl. Если вы хотите, чтобы ваши элементы управления имели определенные свойства и методы, почему бы просто не сделать класс BaseControl (который не наследуется ни от кого, кроме объекта), а иметь наследуемые им будущие элементы управления. Возможно, абстрактный базовый класс или интерфейс - это то, что вам нужно.
Для MVVM проектов WPF у меня обычно есть BaseViewModel, который реализует INotifyPropertyChanged для меня, поэтому мне не нужно делать тот же код везде.
Удачи, я знаю, что эта проблема была огромной болью, чтобы понять. Сообщение об исключении и google наиболее бесполезны!
Ответ 2
Разочаровательно, у меня была именно эта ошибка и потратил навсегда попытку выработать причину. Для меня это работало, но затем я внес некоторые незначительные изменения в XAML производного элемента управления, и компилятор начал давать это сообщение об ошибке.
Короткое решение, вырезающее много часов, пытаясь понять это: закрыл Visual Studio и снова открыл его, перекомпилировал, проблема волшебным образом ушла! (Это VS2012 Pro)
Просто добавьте это, если кто-нибудь читает круги вокруг, пытаясь найти несуществующую проблему с их кодом. Возможно, стоит попробовать "Решение IT Crowd".
Ответ 3
Причина, по которой вы получаете эту ошибку, состоит в том, что метод InitializeComponent, который реализован (в VS 2010), всегда будет искать в сборке производного класса.
Вот 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
}
Линией, где он ищет ваш ресурс XAML, является System.Windows.Application.LoadComponent(это, resourceLocator). И это, скорее всего, не получается, потому что эквивалент "this.GetType(). Assembly" используется для определения того, какая сборка предназначена для поиска ресурса, идентифицированного относительным Uri. И 'this.GetType()' получает производный тип объекта, а не тип класса, в котором реализован код.
PS. Это ошибка? Я не знаю...
Ответ 4
Это дало мне головные боли в течение 3 дней! У меня есть XAML UserControl в библиотеке классов и класс (только С#), который происходит из UserControl в моем проекте .exe.
В xaml-дизайнере моего MainWindow.xaml и при запуске приложения я получил ошибку "у компонента нет ресурса, идентифицированного с помощью uri".
Ответ "Хуана Карлоса Гирона", наконец, привел меня к решению:
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
}
}
}
}
и вызвал это из файла UserControl.cs:
namespace ClassLibrary1
{
public partial class MyUserControl : UserControl
{
public MyUserControl()
{
//InitializeComponent();
this.LoadViewFromUri("/ClassLibrary1;component/myusercontrol.xaml");
}
}
}
Еще раз спасибо "Хуан Карлос Гирон"!
Ответ 5
Вы можете попробовать этот подход
Я создал свой собственный InitializeComponent()
, и я назвал этот путь
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
}
}
Ответ 6
Такая же проблема здесь.
Краткая версия:
Копировать Локальный должен быть установлен на False!
Длинная версия:
Мы разработали WPF-решение (MVVM, 20 проектов) и внедрили подключаемую систему. Наш каталог /bin/Debug содержит исполняемый файл, некоторые файлы dll и каталог плагинов, который содержит плагины.
Существует один проект "DialogLib" (библиотека классов, вид диалога), который определяет окно (представление), ViewModel, Model и некоторые интерфейсы. Один из плагинов использовал один из интерфейсов DialogLib. Само окно открывается основным приложением.
Чтобы использовать интерфейс библиотеки "DialogLib" в плагине, нам пришлось добавить ссылку на проект DialogLib в ссылки на проекты плагинов. Когда приложение было запущено, плагины были загружены. Если пользователь выбирает пункт меню, откроется окно. На этом этапе ошибка "... компонент не имеет ресурса, идентифицированного с помощью URI...", произошла, когда код Windows позади попытался выполнить его InitializeComponent().
Где проблема?
Проблема заключается в том, что при построении решения VS корректно создал DialogLib.dll и скопировал его в /bin/Debug/. Это связано с тем, что основной файл приложения хочет открыть окно. Но DialogLib.dll также был скопирован в /bin/Debug/plugins, потому что один из плагинов ссылался на него, чтобы использовать один из интерфейсов, определенных в DialogLib.dll. Итак, что?
Когда плагин загружается во время выполнения, он использует интерфейс, определенный в /bin/Debug/plugins/DialogLib.dll. и основной файл приложения пытается открыть окно, определенное в /bin/Debug/DialogLib.dll. Хотя файлы идентичны, VS сталкивается с проблемами. Установка значения "Копировать локальное" в ссылочных свойствах DialogLib ссылок плагинов позволяет избежать копирования DialogLib.dll в /bin/Debug/plugins и, таким образом, решает проблему.
У нас была аналогичная проблема (но другая ошибка) в другом проекте, где мы хотели использовать тип TypeA, который был определен в DLL файле, в плагине и в основном приложении. Copy Local был установлен в значение true, из-за чего копия файла dll была расположена в.. /bin/Debug/plugins и в.. /bin/Debug/. Оказалось, что, хотя это был один и тот же файл dll, TypeA в главном файле приложения и TypeA в плагине рассматривались как разные типы соответственно как типы, которые не могли быть обменены.
Ответ 7
Я решил это, разместив
myusercontrol = Activator.CreateInstance<myusercontrol>();
в конструкторе окна, содержащего пользовательский контроль до строки InitializeComponent();
Ответ 8
- Удалить папку
obj
- Удалить папку
bin
- Реконструкция
Работал для меня!
Также, если вы загружаете сборки с помощью Assembly.LoadFile
, проверьте AppDomain.CurrentDomain.GetAssemblies()
для дубликатов сборок в текущем AppDomain. Поскольку в автоматическом сгенерированном коде WPF UserControl компонент будет загружен с использованием его относительного URI. А поскольку в текущем AppDomain есть дубликаты сборок, приложение не знает, какой из них использовать.
Ответ 9
Я получил ту же ошибку при использовании Visual Studio 2013.
У компонента нет ресурса, идентифицированного uri
Пробовал:
Очистка и восстановление решения - не сработало.
Закрытие и открытие Visual Studio - не сработало.
Решение:
Зашел в каталог проектов bin
и очистил все файлы.
Удалил проект и работал нормально.
Откройте Консоль диспетчера пакетов, которая откроется в корневом каталоге вашего решения и запустит следующую команду powershell:
Get-ChildItem -inc bin,obj -recurse | Remove-Item -recurse -force -EA SilentlyContinue
Ответ 10
@Виллем, мне это кажется совершенно нормально. На самом деле я попробовал это, и это сработало в моем случае. Я использовал ListBox
вместо DataGrid
(но это не должно иметь значения).
Все мои пространства имен были в одной сборке. Поэтому я использовал общее родительское пространство имен для всех, например.
MyWpfApplication.Controls
MyWpfApplciation.GridView
MyWpfApplciation.ViewBase
Coz все эти Controls
, GridView
, ViewBase
сталкиваются с существующими пространствами имен System
или System.Windows.Controls
и декларациями классов. Поэтому я убедился, что в своем проекте я указал правильные MyWpfApplication.*
.
Ответ 11
Я получил эту ошибку после переименования файла xaml. Реверсирование переименования решило проблему.
Кроме того, я обнаружил, что ссылка на имя файла xaml в App.xaml не была обновлена (StartupUri), но переименование этого имени не устранило проблему (но, возможно, это для вас). В принципе, я не могу переименовать файл xaml.
Fyi, для меня компонент, "жалующийся" в ошибке, был SplitComboBox.
Ответ 12
Слушай, когда у меня был тот же проект, открытый в двух решениях. Изменение базового управления в одном проекте заставляет другой проект иметь эту проблему. Если закрытие и открытие не работают, удалите все папки в папке "C:\Users...\AppData\Local\Microsoft\VisualStudio\12.0\Designer\ShadowCache"
Ответ 13
Это может произойти также при закрытии и повторном открытии окна. Таким образом, он также не может иметь ничего общего с пакетами и/или dll.
Я решил проблему благодаря решению, опубликованному PainElemental, которое ИМХО недооценивается:
namespace MyNamespace
{
public partial class MyDialog : Window
{
public MyDialog(ExcelReference sheetReference)
{
this.LoadViewFromUri("/MyApp;component/mynamespace/mydialog.xaml");
}
}
}
LoadViewFromUri реализуется как расширение, как пишет PainElemental.
Самым сумасшедшим является то, что я также написал в том же проекте другие окна, не сталкиваясь с какой-либо проблемой.
Спасибо PainElemental, ты закончил мою затяжную боль!
Ответ 14
Я тоже столкнулся с этой проблемой без каких-либо проблем с наследованием. Я просто ссылался на DLL, содержащую диалог и пытающийся создать и отобразить этот диалог.
У меня есть сборщик, который загружает сборки из определенной папки, и получается, что я добавил ссылку в VS и не отключил Copy Local. Короче говоря: мой процесс загрузил две версии той же DLL. Кажется, это путает WPF (или время выполнения). Как только я очистил копию Local и удалил лишние копии DLL, он снова работал нормально.
Ответ 15
Быстрее закрытия всей Visual Studio просто для того, чтобы убить XDescProc.exe в вашем диспетчере задач.
XDescProc - дизайнер. В тот момент, когда процесс будет закрыт, вы увидите ссылку "Обновить конструктор" в визуальной студии. Нажмите это, и XDes снова запустится, и ваша ошибка "нет ресурса" исчезнет.
Здесь визуальная студия link показывает после того, как вы убьете конструкторский процесс:
![введите описание изображения здесь]()
Ответ 16
Я случайно удалил пользовательский элемент управления с помощью действия переименовать/ копировать. Когда я восстановил файл проекта и файл xaml и .cs из контроля версий, эта ошибка начала происходить в студии дизайна для этого элемента управления, который был ошибочно удален/переименован.
Это предложило некоторый тип кеша в рассматриваемом файле.... поэтому закрытие Visual Studio, удаление каталога bin
и восстановление выполнялись.
Ответ 17
Следуя решению PainElemental (чтобы уточнить, для моего кода ClassLibrary1 для меня было имя .dll без расширения .dll), здесь мой сценарий на случай, если он поможет кому-либо связать свои конкретные сообщения об ошибках с проблемой:
Я использую dll для загрузки и запуска пользовательских контролей в основную программу как свои собственные всплывающие окна. Решение PainElemental в основном работало, но 1 из 3 классов в моем "popup.dll" не загружался должным образом. Я бы получил исключение с двумя внутренними исключениями, например:
mscorlib InvokeMethod...;
WpfXamlLoader.Load... Укажите значение для... StaticResourceExtension...;
ResolveBamlType.... метод или операция не реализованы.
В моем случае я подтвердил, что он загрузит новый URI и будет работать при тестировании, но когда я попытался запустить его в моей среде Live, в LoadViewFromUri() произойдет ошибка.
В ходе дальнейшего тестирования я сузил проблему до невозможности загрузки отдельного файла "library.dll", который я использовал, который содержал конвертер, который я использовал в файле .xaml класса, который не работал, и дальнейших исследований. проблема заключалась в том, что в среде Live использовалась версия "library.dll", отличная от той, что использовалась в моей тестовой среде, хотя в сообщении об исключении из моей "popup.dll" об этом ничего не упоминалось.
Для справки я использую Copy Local = True, и это не доставило мне проблем. Чтобы лучше всего отладить такие проблемы, полезно знать, где файлы .dll ищут .exe. Насколько я понимаю, когда вы запускаете проекты в VS, когда Copy Local = True, DLL файлы копируются в ту же папку, что и EXE файл при его сборке. Когда .exe запускается в стандартном расположении, он ищет .dlls в той же папке, что и .exe. Дополнительные местоположения, которые .exe может искать .dll, могут быть установлены в файле .exe.config, в элементе probeing. В приведенном ниже примере он также может выполнять поиск в каталоге "MyDLLs" и "MyDLLs\Core" относительно расположения .exe. Обратите внимание, что он не будет естественно искать какие-либо подпапки, вы должны указать их явно. Я считаю, что это также ищет GAC, но в настоящее время я обладаю минимальными знаниями о GAC.
<configuration>
...
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<probing privatePath="MyDLLs;MyDLLs\Core;"/>
</assemblyBinding>
</runtime>
</configuration>
Ответ 18
Я начал постоянно видеть ошибку "компонент не имеет ресурса, идентифицируемого uri", когда щелкаю конкретный пункт меню из установленного продукта, который работал на других компьютерах. Я попытался удалить продукт, убедившись, что его файлы действительно исчезли, перезагрузить и переустановить продукт. Проблема осталась. Я удалил содержимое своего каталога% TEMP%, и проблема прекратилась.