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

Избегайте ошибок конструктора Visual Studio, когда ресурс WPF определен в отдельном проекте

Как я могу избежать ошибок конструктора Visual Studio, когда ресурс WPF определен в отдельном проекте?

У меня есть три проекта в составном приложении WPF: основное приложение, библиотека "инфраструктуры" и "модульная" библиотека. Основное приложение ссылается на другие проекты через их выходные DLL (проекты не расположены в одном решении вместе).

Я определяю скин (некоторые кисти и стили в ResourceDictionary) в библиотеке "инфраструктура". Я хотел бы, чтобы основное приложение выбирало скин и делало его доступным для всего приложения (через MergedDictionaries в App.xaml).

В моем модуле я хочу использовать ресурсы, определенные на скине, которые загружаются основным приложением. Если я ссылаюсь на ресурс, как если бы он был локально доступен следующим образом:

Background={StaticResource MainBackgroundBrush}

почти все работает по своему желанию. Исключением является то, что дизайнер Visual Studio путается и говорит мне, что "ссылка StaticResource" MainBackgroundBrush "не найдена". Это эффективно мешает мне использовать конструктор.

Что я могу сделать, чтобы определить "скин" ResourceDictionary в проекте, ссылку на этот скин в главном приложении, а затем использовать его ресурсы в проекте модуля?

4b9b3361

Ответ 1

Одним из возможных решений является использование DynamicResource, а не StaticResource. Дизайнер Visual Studio 2008 просто отображает элементы управления без какого-либо стиля, например, VS2010 beta 1, если он не может разрешить StaticResource.

Использование DynamicResource применимо в ситуациях, когда определенный стиль может меняться во время выполнения, например, при скинировании.

Я нашел некоторые связанные с этим вопросы:

Я также нашел человека, который утверждает, что DynamicResource следует использовать всякий раз, когда ресурс не является локальным:

Ответ 2

Вы можете создать свой собственный класс ResourceDictionary, наследующий от ResourceDictionary. Затем вы можете организовать, что во время разработки этот пользовательский ResourceDictionary загружает некоторые явно определенные стили (т.е. Загруженные из приложения во время выполнения), тогда как во время выполнения он ничего не делает. Свойство IsInDesignMode-Property можно было бы оценить для этого.

Скажем, у вас есть такой класс, называемый "DesignTimeResourceDictionary", тогда вы просто используете s.th. как

 <UserControl.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <Util:DesignTimeResourceDictionary Source="SomeUriToYourResources"/>
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
 </UserControl.Resources>

чтобы загрузить ваши ресурсы во время разработки и сделать работу дизайнера. В Runtime вы можете сделать ваш DesignTimeResourceDictionary пропустить загрузку ресурсов и добиться желаемого поведения.

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

Ответ 3

Я просто хочу продлить ответ Саймона Д.. То, что он предлагает, - это решение, которое я использую прямо сейчас. Я просто хотел поделиться полным исходным кодом. Именно из этого Trick Использовать источник ResourceDictionary только в режиме дизайна.

public class DesignTimeResourceDictionary : ResourceDictionary
{
    /// <summary>
    /// Local field storing info about designtime source.
    /// </summary>
    private string designTimeSource;

    /// <summary>
    /// Gets or sets the design time source.
    /// </summary>
    /// <value>
    /// The design time source.
    /// </value>
    public string DesignTimeSource
    {
        get
        {
            return this.designTimeSource;
        }

        set
        {
            this.designTimeSource = value;
            if ((bool)DesignerProperties.IsInDesignModeProperty.GetMetadata(typeof(DependencyObject)).DefaultValue)
            {
                base.Source = new Uri(designTimeSource);
            }
        }
    }

    /// <summary>
    /// Gets or sets the uniform resource identifier (URI) to load resources from.
    /// </summary>
    /// <returns>The source location of an external resource dictionary. </returns>
    public new Uri Source
    {
        get
        {
            throw new Exception("Use DesignTimeSource instead Source!");
        }

        set
        {
            throw new Exception("Use DesignTimeSource instead Source!");
        }
    }
}

<Window x:Class="WpfApplication1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation Jump "
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml Jump "
    Title="MainWindow" Height="350" Width="525"
    xmlns:local="clr-namespace:WpfApplication1">

  <Window.Resources>
    <local:DesignTimeResourceDictionary DesignTimeSource="pack://application:,,,/BlueColors.xaml"/>
  </Window.Resources>

    <Grid>
      <Button Background="{DynamicResource defaultBackground}"
      HorizontalAlignment="Center" VerticalAlignment="Center">click me</Button>
    </Grid>
</Window>