Есть ли способ использовать StaticResource в управляющей библиотеке WPF и иметь возможность просмотра во время разработки?

У меня есть библиотека управления WPF, которая добавляется в приложение Windows Forms. Мы хотим, чтобы элементы управления были локализуемыми, однако я не уверен, как ПОЛНОСТЬЮ выполнить это без дублирования кода.Это то, что я делаю сейчас.

По сути, в приложении Windows Forms перед запуском основного приложения я создаю экземпляр App.xaml, который находится в приложении форм (содержит мои ссылки на мои ресурсы, которые также находятся в приложении форм). Это отлично работает для времени выполнения.

Тем не менее, все мои пользовательские элементы управления имеютContent="{StaticResource SomeVariableName}", который в конечном итоге будет пустым. Я могу исправить это, имея app.xaml и соответствующие словари ресурсов в моей управляющей библиотеке, которые соответствуют тем, которые есть в моем приложении windows form. Однако это дублированный код.

Вещи, которые я уже пытался безрезультатно:

Instantiate the App.xaml that lives within the user control library from within my forms app. This does not work because the URIs to my resources is looking for an embedded resource, not my local resource dictionary (I could then simply copy the resource files from the control to an appropriate location within my forms app on build). Could I leverage DeferrableContent here? There is not much online as far as I could find on this attribute and how it should be used, though. I would like to use post builds for both App and dictionaries, however, the App instantiation is a static reference to a compiled App.xaml as far as I can tell. So, App.xaml must live within the form at least I did try to have a duplicated App.xaml with a post build moving the resourcedictionary.xaml. I figured that a duplicated app.xaml is ok since that is the driving force and you might not want to rely on one from the control anyway (which circles back and makes you wonder if you should then have the App.xaml in the control at all? Unless you want to allow a default that uses embedded resources....) That too failed saying it could not find the resource even though it was placed where the URI should have been pointing to. The decompiled code points to Uri resourceLocater = new Uri("/WindowsFormsApplication3;component/app.xaml", UriKind.Relative);

Итак, есть ли способ, чтобы это работало И имел представление времени разработки компонентов по умолчанию И избегал дублирования? Или в этом случае все в порядке? Если мой подпункт 2-го маркера выглядит нормально (дублированный файл App.xaml со скопированными сборками ресурсов), как мне сделать так, чтобы он не искал элемент уровня компонента, а вместо этого файл первого уровня?

Последний вопрос (и я могу опубликовать его отдельно, если необходимо), на который я только что обратил внимание. Мой App.xaml встраивается в код, так что в любом случае я не могу создавать новые ResourceDictionaries. Есть какой-либо способ сделать это?

Final option...possibly the best one? - В любом случае я планирую использовать код Андре ван ХеервардеИтак, я должен просто проверить наличие файла и добавить его как объединенный ресурс на лету? По сути, в моем пользовательском элементе управления есть один App.xaml, который ссылается на встроенный ResourceDictionary по умолчанию. И затем код должен искать соответствующие локализованные ресурсы на лету, которые могут быть относительными путями файлов? Единственный недостаток, который я вижу здесь, это то, что значение по умолчанию не может быть изменено на лету ... что я, возможно, даже мог бы иметь такой вид в указанном месте (используя какое-то соглашение) и предпочел бы этот вариант встроенному?

Да, и причина, по которой я не хочу встраивать ресурсы, заключается в том, что конечные пользователи могут добавлять / изменять новые локализованные ресурсы после развертывания сборки.

Я могу добавить код, если он поможет вам лучше это представить, просто дайте мне знать.

UPDATE

Сейчас я сталкиваюсь с еще одной проблемой со стилем, а не только с локализацией.

Вот пример одной из внутренних кнопок на одном из элементов управления:

<code><Button Style="{StaticResource GrayButton}"
</code>

Еще несколько вещей, которые я пробовал / думал:

I cannot create an app.xaml (that would never be used) with the ResourceDictionary set up as ApplicationDefinitions are not allowed in library projects. I could embed this in the control's resources, but then that would always take precedence over any application level resources and I lose customizability.

Вот случай подключения это на самом деле звучит как то, что я ищу, однако это не дает никакого реального решения этой проблемы.

Решение (за пределами вершины ... которое не работает), о котором я могу подумать, может сработать (и еще не попробовало), также кажется большой работой для чего-то, что, на мой взгляд, должно быть простым. Но я мог бы создать некоторые свойства зависимостей в элементе управления, к которым я могу привязаться, и затем разрешить их переопределение проектом, который будет использовать этот элемент управления. Как я уже сказал, для довольно простого запроса это кажется большой работой :). Будет ли это даже работать? И что еще более важно, есть ли лучшее, более простое решение, которое мне не хватает?

Ответы на вопрос(3)

Решение Вопроса

Однажды я столкнулся с этой проблемой, и решил ее, отбросив все "Ресурсы - это объекты, проиндексированные по ключу в канонических словарях". вещь.

Я имею в виду простой факт определения ресурса в одном проекте и ссылки на него в другом по его «ключу». должен давать мурашки по коже любому здравомыслящему человеку. я хотелstrong Рекомендации.

Мое решение этой проблемы было создатьпользовательский инструмент который преобразует мои файлы ресурсов xaml в статические классы со свойством для каждого ресурса:

Итак, MyResources.xaml:

<ResourceDictionary>
  <SolidColorBrush x:Key="LightBrush" ... />
  <SolidColorBrush x:Key="DarkBrush" ... />
</ResourceDictionary>

Становится MyResources.xaml.cs

public static class MyResources {

  static MyResources() {
    // load the xaml file and assign values to static properties
  }

  public static SolidColorBrush LightBrush { get; set; }
  public static SolidColorBrush DarkBrush { get; set; }

}

Для ссылки на ресурс вы можете использоватьx:Static вместоStaticResource:

<Border 
   Fill="{x:Static MyResources.LightBrush}"
   BorderBrush="{x:Static MyResources.DarkBrush}"
   ... />

Теперь у вас есть надежные ссылки, автозаполнение и проверка времени компиляции ресурсов.

 27 апр. 2014 г., 10:32
XAML анализируется и компилируется в каждой среде выполнения или при каждой сборке?
 18 июн. 2013 г., 20:24
+1 гениально! Никогда даже не приходило в голову подойти к этому так!
 27 апр. 2014 г., 14:41
@ZevSpitz Каждый раз, когда вы сохраняете файл XAML, Visual Studio запускает на нем пользовательский инструмент, очень похожий на шаблон T4. Так что это даже не время сборки, это время выпуска!
 Justin Pihony26 апр. 2012 г., 16:20
+1 Это лучший ответ, который я когда-либо видел на самом деле. Делая это, я могу поместить свой ресурсный код куда угодно и заставить его работать так, как мне нужно. Но как это будет работать в дизайнере? Будет ли он обновлять экземпляр MyResources и использовать значения по умолчанию?
 26 апр. 2012 г., 16:34
Насколько я помню, да.

У меня тоже была проблема с темами оформления и доступными статическими ресурсами. Итак, я создал автономную библиотеку, в которой в основном не было ничего, кроме используемых тем, все вложенные, как ваши ресурсы MERGED вашего предыдущего связанного вопроса.

Затем в форме Windows (.xaml) я просто поместил ссылку на эту библиотеку, что-то вроде

<Window x:Class="MyAppNamespace.MyView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" ... />

  <Window.Resources>
    <ResourceDictionary>
      <ResourceDictionary.MergedDictionaries>
        <!-- Common base theme -->
        <ResourceDictionary   Source="pack://application:,,,/MyLibrary;component/Themes/MyMainThemeWrapper.xaml" />
        </ResourceDictionary.MergedDictionaries>
      </ResourceDictionary>
  </Window.Resources>

  <Rest of XAML for the WPF window>

</Window>

& Quot; компонент & quot; по-видимому, ссылается на корень данного «MyLibrary» проект. В настоящем проекте я создал подпапку «Темы», поэтому источник включает в себя ...; компонент / Темы / ...

& Quot; MyMainThemeWrapper.xaml & quot; очень похож на ваши вложенные словари Merged Resource, и он отлично видит все из других библиотек.

 Justin Pihony20 апр. 2012 г., 18:16
Это не распространится на мой UserControl во время разработки. И даже если бы я ссылался на библиотеку словаря ресурсов в моем UserControl, он все равно был бы встроен в UserControl. Возможно, мне понадобится прояснить вопрос, но мне нужно кое-что, с чем можно поработать при проектировании (по умолчанию), которое затем можно переопределить во время выполнения (контент resourcedictionary.xaml, не внедренный)

Вот мойpartial Решение вашей проблемы. Я не пытался обрабатывать свободные ресурсы, но у меня есть некоторый успех в совместном использовании ресурсов между WinForms и WPF.

Create a class library to contain your resources in .ResX files (e.g. Resources.resx, Resources.fr.resx, etc) Create your WPF controls in a WPF user control library Create your WinForms host

Reference the resources in your resource library from WPF using the Infralution.Localization.Wpf markup extension and culture manager, e.g.

<TextBlock Text="{Resx ResxName=ResourceLib.Resources, Key=Test}"/>

Put the content of your WPF user controls into one or more resource dictionaries as control templates,e,g

<ControlTemplate x:Key="TestTemplate">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>

        <TextBlock Text="{Resx ResxName=ResourceLib.Resources, Key=Test}"/>
    </Grid>
</ControlTemplate>

Use the resource template in your user controls

<UserControl x:Class="WpfControls.UserControl1"
             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:d="http://schemas.microsoft.com/expression/blend/2008" mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300" >
    <UserControl.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="ResourceDictionary.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </UserControl.Resources>
    <ContentControl Template="{StaticResource TestTemplate}" />
</UserControl>

Add a couple of lines of code to make things work

public partial class UserControl1 : UserControl
{
    // we require a reference to the resource library to ensure it's loaded into memory
    private Class1 _class1 = new Class1();

    public UserControl1()
    {
        // Use the CultureManager to switch to the current culture
        CultureManager.UICulture = Thread.CurrentThread.CurrentCulture;

        InitializeComponent();
    }
}

Вот простойдемонстрационное приложение называется WindowsFormsHost.7z

 25 апр. 2012 г., 22:28
Что ж, я исправляю «Content =» {StaticResource SomeVariableName} ». проблема, помещая ContentControl в свой UserControl, не вмешиваясь в app.xaml. UserControl локализуем и разделяет ресурсы с WinForms, используя файлы .ResX. Как это так же?
 Just,in Pihony25 апр. 2012 г., 22:23
Чем это отличается от того, что предложил @DRapp?

Ваш ответ на вопрос