VsBrush 在 WPF ResourceDictionary 中不起作用
VsBrush doesn't work in WPF ResourceDictionary
tl;dr
问题描述
首先,我是 WPF 的新手,我现在几乎不知道我在做什么...
我正在开发 a Visual Studio 2013 扩展,我在其中创建了一个自定义工具 Window。由于 WPF 控件不 从父级继承主题(即 Visual Studio main window),您必须手动进行。
我读到我应该使用 Microsoft.VisualStudio.Shell.VsBrushes or the Microsoft.VisualStudio.PlatformUI.EnvironmentColors classes as they define the Visual Studio shell theme specific constants. (See example here.) 只要我在 Style
标签中使用它就可以正常工作。
但是,Microsoft 的 Menu and MenuItem ControlTemplate Example 解释了如何使用 <ContentTemplate>
制作正确的 MenyItem 模板。
问题是,VsBrush 和 EnvironmentColors 都不能在 <ContentTemplate>
中工作。当我为 <GradintStop>
设置颜色时出现 一般异常 抱怨(没有详细信息,问题是什么), 或 UI只是挂起,甚至没有加载。在后一种情况下,当我中断应用程序时,我总是进入 MS.Win32.UnsafeNativeMethods.GetMessageW()
函数。
问题
- 有人可以解释一下我做错了什么以及为什么我不能在我的
<ContentTemplate>
中使用 VsBrushes
和 EnvironmentColors
classes 吗?
- 如何使用建议的
<ContentTemplate>
格式正确设计我的 Visual Studio 扩展?
尝试解决问题
- 我检查了整个包的构造函数,可以获取
VsBrushes
class 的颜色常量。仅在构造函数后 UI 挂起,因此 VsBrushes
值必须在处理 XAML 时初始化。
- 如上所述,不使用
<ControlTemplate>
常量也可以使用。
- 调查异常:当解析器试图解释
<GradientStop>
标签的颜色 属性 时抛出。没有解释到底是什么失败了。 (过了一会儿——随着代码稍微改变——异常停止,UI 挂起开始。)
- 如果我将
LinearGradientBrush
更改为 SolidColorBrush
问题仍然存在(当然这次例外情况略有不同): 'Set 属性 'System.Windows.Media.SolidColorBrush.Color' throw an异常。
- 问题不
<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>
调用堆栈
这是进程所在"hangs":
[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
分辨率
以下所有这些 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 是无类型的(一切都是字符串)。由于错误消息('Set 属性 'System.Windows.Media.LinearGradientBrush.Color' throw an exception.)并不是很健谈,它并不能真正帮助你理解你做错了什么。
经验教训
如果编译器没有为您检查类型(或者没有告诉您这是导致问题的原因),请尝试手动检查类型。
tl;dr
问题描述
首先,我是 WPF 的新手,我现在几乎不知道我在做什么...
我正在开发 a Visual Studio 2013 扩展,我在其中创建了一个自定义工具 Window。由于 WPF 控件不 从父级继承主题(即 Visual Studio main window),您必须手动进行。
我读到我应该使用 Microsoft.VisualStudio.Shell.VsBrushes or the Microsoft.VisualStudio.PlatformUI.EnvironmentColors classes as they define the Visual Studio shell theme specific constants. (See example here.) 只要我在 Style
标签中使用它就可以正常工作。
但是,Microsoft 的 Menu and MenuItem ControlTemplate Example 解释了如何使用 <ContentTemplate>
制作正确的 MenyItem 模板。
问题是,VsBrush 和 EnvironmentColors 都不能在 <ContentTemplate>
中工作。当我为 <GradintStop>
设置颜色时出现 一般异常 抱怨(没有详细信息,问题是什么), 或 UI只是挂起,甚至没有加载。在后一种情况下,当我中断应用程序时,我总是进入 MS.Win32.UnsafeNativeMethods.GetMessageW()
函数。
问题
- 有人可以解释一下我做错了什么以及为什么我不能在我的
<ContentTemplate>
中使用VsBrushes
和EnvironmentColors
classes 吗? - 如何使用建议的
<ContentTemplate>
格式正确设计我的 Visual Studio 扩展?
尝试解决问题
- 我检查了整个包的构造函数,可以获取
VsBrushes
class 的颜色常量。仅在构造函数后 UI 挂起,因此VsBrushes
值必须在处理 XAML 时初始化。 - 如上所述,不使用
<ControlTemplate>
常量也可以使用。 - 调查异常:当解析器试图解释
<GradientStop>
标签的颜色 属性 时抛出。没有解释到底是什么失败了。 (过了一会儿——随着代码稍微改变——异常停止,UI 挂起开始。) - 如果我将
LinearGradientBrush
更改为SolidColorBrush
问题仍然存在(当然这次例外情况略有不同): 'Set 属性 'System.Windows.Media.SolidColorBrush.Color' throw an异常。 - 问题不
<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>
调用堆栈
这是进程所在"hangs":
[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
分辨率
以下所有这些 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 是无类型的(一切都是字符串)。由于错误消息('Set 属性 'System.Windows.Media.LinearGradientBrush.Color' throw an exception.)并不是很健谈,它并不能真正帮助你理解你做错了什么。
经验教训
如果编译器没有为您检查类型(或者没有告诉您这是导致问题的原因),请尝试手动检查类型。