Подтвердить что ты не робот

У компонента нет ресурса, идентифицированного 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'."

Что я делаю неправильно?

Является ли это правильным подходом или нет?

4b9b3361

Ответ 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%, и проблема прекратилась.