VsBrush не работает в WPF ResourceDictionary

ТЛ; др

Описание проблемы

Прежде всего, я новичок в WPF, и у меня пока мало что получается, что я делаю...

Я разрабатываю расширение Visual Studio 2013, в котором я создаю собственное окно инструментов. Поскольку элементы управления WPF не наследуют темы от родительского (т. Е. Главное окно Visual Studio), вы должны сделать это вручную.

Я прочитал, что должен использовать классы Microsoft.VisualStudio.Shell.VsBrushes или Microsoft.VisualStudio.PlatformUI.EnvironmentColors, поскольку они определяют конкретные константы темы оболочки Visual Studio. ( См. Пример здесь.) Это прекрасно работает, пока я использую это в Style тег.

Тем не менее, в Microsoft Menu и MenuItem ControlTemplate Example объясняется, как сделать правильный шаблон MenyItem с помощью<ContentTemplate>, Проблема в том, что ни VsBrush, ни EnvironmentColors не работают в <ContentTemplate>, Либо есть общее исключение, жалующееся, когда я устанавливаю цвет для <GradintStop> (без подробностей, в чем проблема), или пользовательский интерфейс просто зависает, даже не загружается. В этом последнем случае, когда я ломаю приложение, я всегда в MS.Win32.UnsafeNativeMethods.GetMessageW() функция.

Вопросы

  1. Может кто-нибудь объяснить, пожалуйста, что я делаю неправильно и почему я не могу использовать VsBrushes а также EnvironmentColors занятия в моем <ContentTemplate>?
  2. Как правильно стилизовать расширение Visual Studio, используя предложенные <ContentTemplate> формат?

Попытки решить проблему

  1. Я проверил в конструкторе всего пакета, что цветовые константы VsBrushes класс можно получить. Только после конструктора пользовательский интерфейс зависает, поэтому VsBrushes значения должны быть инициализированы к моменту обработки XAML.
  2. Как указано выше, без использования <ControlTemplate> константы могут быть использованы.
  3. Исследовано исключение: оно было выдано, когда синтаксический анализатор попытался интерпретировать свойство Color <GradientStop> тег. Нет объяснения, что именно не удалось. (Через некоторое время - когда код немного изменился - исключение прекратилось и началось зависание интерфейса.)
  4. Если я изменю LinearGradientBrush в SolidColorBrush проблема все еще сохраняется (конечно, на этот раз исключение немного отличается): 'Set property 'System.Windows.Media.SolidColorBrush.Color'вызвала исключение.
  5. Проблема не в <MenuItem> конкретный. Это может быть воспроизведено с <Button> и я думаю, с любым произвольным управлением WPF.

Источник

Вот код, который я использую для определения моего стиля для MenuItems:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:vsShell="clr-namespace:Microsoft.VisualStudio.Shell;assembly=Microsoft.VisualStudio.Shell.12.0"
                    xmlns:vsUI="clr-namespace:Microsoft.VisualStudio.PlatformUI;assembly=Microsoft.VisualStudio.Shell.12.0">
    <Color x:Key="MyColor">#FFFFFF00</Color>
    <Style x:Key="{x:Type Menu}" TargetType="{x:Type Menu}">
        <Setter Property="OverridesDefaultStyle" Value="True" />
        <Setter Property="SnapsToDevicePixels" Value="True" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Menu}">
                    <Border BorderThickness="1">
                        <Border.BorderBrush>
                            <LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5">
                                <LinearGradientBrush.GradientStops>
                                    <GradientStopCollection>
                                        <GradientStop Color="{DynamicResource MyColor}" Offset="0.0" />
                                        <GradientStop Color="{DynamicResource {x:Static SystemColors.ActiveBorderColorKey}}" Offset="0.1" />
                                        <GradientStop Color="#FF00FF00" Offset="0.5" />
                                        <!-- The following 3 do not work -->
                                        <GradientStop Color="{DynamicResource {x:Static vsUI:EnvironmentColors.AccentBorderBrushKey}}" Offset="0.8" />
                                        <GradientStop Color="{DynamicResource {x:Static vsShell:VsBrushes.AccentBorderKey}}" Offset="0.8" />
                                        <GradientStop Color="{DynamicResource VsBrush.AccentBorder}" Offset="1.0" />
                                    </GradientStopCollection>
                                </LinearGradientBrush.GradientStops>
                            </LinearGradientBrush>
                        </Border.BorderBrush>
                        <Border.Background>
                            <LinearGradientBrush EndPoint="0,0.5" StartPoint="1,0.5">
                                <GradientStop Color="Blue" Offset="0" />
                                <GradientStop Color="Blue" Offset="1" />
                            </LinearGradientBrush>
                        </Border.Background>
                        <StackPanel ClipToBounds="True" Orientation="Horizontal" IsItemsHost="True" />
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

Стек вызовов

Вот где процесс "зависает":

[Managed to Native Transition]  
>   WindowsBase.dll!MS.Win32.UnsafeNativeMethods.GetMessageW(ref System.Windows.Interop.MSG msg, System.Runtime.InteropServices.HandleRef hWnd, int uMsgFilterMin, int uMsgFilterMax) Line 566  C#
WindowsBase.dll!System.Windows.Threading.Dispatcher.GetMessage(ref System.Windows.Interop.MSG msg, System.IntPtr hwnd, int minMessage, int maxMessage) Line 391 C#
WindowsBase.dll!System.Windows.Threading.Dispatcher.PushFrameImpl(System.Windows.Threading.DispatcherFrame frame) Line 979  C#
WindowsBase.dll!System.Windows.Threading.Dispatcher.PushFrame(System.Windows.Threading.DispatcherFrame frame) Line 961  C#
WindowsBase.dll!System.Windows.Threading.Dispatcher.Run() Line 1059 C#
Microsoft.VisualStudio.Shell.12.0.dll!Microsoft.Internal.VisualStudio.PlatformUI.BackgroundDispatcher.ThreadProc(object arg)    Unknown
mscorlib.dll!System.Threading.ThreadHelper.ThreadStart_Context(object state)    Unknown
mscorlib.dll!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx)   Unknown
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx)   Unknown
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) Unknown
mscorlib.dll!System.Threading.ThreadHelper.ThreadStart(object obj)  Unknown

1 ответ

Решение

разрешение

Все эти следующие 3 строки вызывают ошибку компиляции, потому что компилятор ожидает Color но я дал ему Brush вместо.

<GradientStop Color="{DynamicResource {x:Static vsUI:EnvironmentColors.AccentBorderBrushKey}}" Offset="0.8" />
<GradientStop Color="{DynamicResource {x:Static vsShell:VsBrushes.AccentBorderKey}}" Offset="0.8" />
<GradientStop Color="{DynamicResource VsBrush.AccentBorder}" Offset="1.0" />

Я должен был использовать <GradientStop Color="{DynamicResource {x:Static vsUI:EnvironmentColors.AccentBorderColorKey}}" Offset="0.8" /> вместо. (Обратите внимание, что я использую AccentBorderColorKey вместо AccentBorderBrushKey.)

XAML разбирает строку и пытается интерпретировать то, что приводит к простому факту: XAML не имеет типов (все является строкой). Так как сообщение об ошибке ("Задать свойство" System.Windows.Media.LinearGradientBrush.Color "вызвало исключение.) Не очень разговорчиво, оно не поможет вам понять, что вы сделали неправильно.

Урок выучен

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

Другие вопросы по тегам