tl;dr
Problem description
First of all, I'm new to WPF and I have little to now idea what I'm doing...
I'm developing a Visual Studio 2013 Extension in which I create a custom Tool Window. Since the WPF controls don't inherit themes from parent (i.e. Visual Studio main window), you have to to it manually.
I read that I should use the Microsoft.VisualStudio.Shell.VsBrushes or the Microsoft.VisualStudio.PlatformUI.EnvironmentColors classes as they define the Visual Studio shell theme specific constants. (See example here.) This works all fine as long as I use this within a Style tag.
However, Microsoft's Menu and MenuItem ControlTemplate Example explains how to do a proper MenyItem template using <ContentTemplate>.
The problem is, that neither the VsBrush nor the EnvironmentColors don't work within the <ContentTemplate>. Either there is a generic exception complaining when I set the color for <GradintStop> (no details, what the problem is), or the UI just hangs, doesn't even load. In this later case when I break the application, I always en up in MS.Win32.UnsafeNativeMethods.GetMessageW() function.
Questions
Could someone please explain what I'm doing wrong and why I can't use the VsBrushes and EnvironmentColors classes in my <ContentTemplate>?
How can I properly style my Visual Studio Extension using the suggested <ContentTemplate> format?
Attempts To Solve The Issue
I checked in the constructor of the whole package, that the color constants of the VsBrushes class can be fetched. Only after the constructor does the UI hang, so the VsBrushes values must be initialized by the time the XAML is processed.
As pointed out above, without the use of <ControlTemplate> the constants can be used.
Investigated the exception: it was thrown when the parser tried to interpret the Color property of the <GradientStop> tag. No explanation what exactly failed. (After a while -- as the code changed a bit -- the exception ceased and the UI hang started.)
If I change the LinearGradientBrush to SolidColorBrush the problem still persists (of course the exception is slightly different this time): 'Set property 'System.Windows.Media.SolidColorBrush.Color' threw an exception.
The problem is not <MenuItem> specific. It can be reproduced with <Button> and I guess with any arbitrary WPF control.
Source
Here's the code I use for defining my style for 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>
Call Stack
This is where the process "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
Resolution
All these following 3 lines cause compilation error, because the compiler expects a Color but I gave it a Brush instead.
<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" />
I should have use <GradientStop Color="{DynamicResource {x:Static vsUI:EnvironmentColors.AccentBorderColorKey}}" Offset="0.8" /> instead. (Notice that I use AccentBorderColorKey instead of AccentBorderBrushKey.)
XAML is parsing string and tries to interpret that which leads to a simple fact: XAML is typeless (everything is a string). Since the error message ('Set property 'System.Windows.Media.LinearGradientBrush.Color' threw an exception.) is not really talkative, it doesn't really help you understand what you did wrong.
Lesson learned
Try to check the type manually if the compiler doesn't do it for you (or doesn't tell you that it is what causes the problem.)
Related
If I change some resource used as StaticResource then all the controls which referring to is affected.
And it does not in case the resource is referred as DynamicResource.
But how about some resource referred as StaticResource in a DynamicResource?
<Color x:Key="Color">#000000</Color>
<LinearGradientBrush x:Key="GradientBrush" EndPoint="0,0" StartPoint="0,1" >
<GradientStop Color="{StaticResource Color}" Offset="0" />
<GradientStop Color="{StaticResource Color}" Offset="1" />
</LinearGradientBrush>
<DrawingBrush x:Key="TabItemBrush" >
<DrawingBrush.Drawing>
<GeometryDrawing Brush="{StaticResource GradientBrush}">
<GeometryDrawing.Geometry>
<RectangleGeometry Rect="0 100 100 100"/>
</GeometryDrawing.Geometry>
</GeometryDrawing>
</DrawingBrush.Drawing>
</DrawingBrush>
<Style TargetType="{x:Type TabItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<Grid x:Name="Root">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="SelectionStates">
<VisualState x:Name="Unselected" >
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetName="Border"
Storyboard.TargetProperty="(Panel.Background).(DrawingBrush.Drawing).(GeometryDrawing.Brush).(GradientBrush.GradientStops)[0].(GradientStop.Color)">
<EasingColorKeyFrame KeyTime="0" Value="Red" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Selected">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetName="Border"
Storyboard.TargetProperty="(Panel.Background).(DrawingBrush.Drawing).(GeometryDrawing.Brush).(GradientBrush.GradientStops)[0].(GradientStop.Color)">
<EasingColorKeyFrame KeyTime="0" Value="Blue" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border x:Name="Border" Background="{DynamicResource TabItemBrush}">
<ContentPresenter x:Name="ContentSite" VerticalAlignment="Center"
HorizontalAlignment="Center" ContentSource="Header"
Margin="12,2,12,2" RecognizesAccessKey="True" />
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Border in TabItem refers TabItemBrush using DynamicResource.
TabItemBrush refers GradientBrush using StaticResource.
GradientBrush refers Color using StaticResource.
<StackPanel>
<TabControl>
<TabItem Header="AAA" >AAA</TabItem>
<TabItem Header="BBB" >BBB</TabItem>
<TabItem Header="CCC" >BBB</TabItem>
</TabControl>
<Border Background="{DynamicResource GradientBrush}" Height="1000" Width="1000"/>
</StackPanel>
I thought that all of TabItem change to same color when I change a selected item in TabControl because all of resources is referred as StaticResource except TabItemBrush.
But only the color of selected item is blue and the others red.
Moreover if i change all the StaticResource to DynamicResource, it works incorrectly ( all red or all blue).
Why StaticResource works as if it is not shared and DynamicResource as shared?
I found your question very difficult to understand. However, I think you are confused because you are not understanding the difference between StaticResource and DynamicResource.
As the names suggest, StaticResource references will/can never change (they are static).
Resources referenced using StaticResource are resolved only once at compile-time.
As the names suggest, DynamicResource references can change (they are dynamic).
Resources referenced using DynamicResource are resolved at runtime.
Since StaticResource references are resolved at compile-time, the XAML parser can avoid the overhead of creating an intermediate lookup expression (which is then executed at runtime).
This is why you should always avoid DynamicResource with the goal to improve the application's performance.
StaticResource does not allow forward references, whereas DynamicResource does - but the forward reference aspect doesn't matter in your context.
"If I change some resource used as StaticResource then all the
controls which referring to is affected."
This is definitely not correct. You can't change resources referenced as StaticResource and then observe that those changes update the referencing objects - this can't have never happened (see explanation of the fundamental characteristics above).
You probably meant something different here.
"I thought that all of TabItem change to same color when I change a selected >item in TabControl because all of resources is referred as StaticResource >except TabItemBrush.
But only the color of selected item is blue and the others red."
This is the correct behavior. You have defined the VisualState objects for "Selected" and "Unselected" with the VisualStateManager. According to these states clicking a TabItem will modify the Background of the selected item to blue and all other unselected items to red.
"Moreover if i change all the StaticResource to DynamicResource, it works >incorrectly ( all red or all blue)."
Here comes in the special behavior of the XAML engine in context of animations: it will freeze the Storyboard.
This means, all participating child instances like AnimationTimeline (e.g., ColorAnimation), or Animatable types in general, are frozen and therefore not changeable (they all inherit Freezable).
As a consequence, all referenced resources like Brush must be static and known at compile-time: you can't reference resources using DynamicResource if the referencing instance needs to be frozen.
Resources used in a Storyboard must be referenced as StaticResource.
Now, given the case that an element, for example a Border, uses DynamicResource to reference a resource that itself contains references to other resources:
If the element uses DynamicResource to reference a pure static resource (a resource that doesn't itself references other resources using DynamicReference), then the XAML engine will optimize the reference by treating it as a StaticResource, to avoid the overhead, and store it in the internal lookup table for the static resources (remember, StaticResource is much cheaper in terms of performance costs than looking up a DynamicResource). This resource can be targeted by a Storyboard animation as it is now static:
<ResourceDictionary>
<Color x:Key="Color">#000000</Color>
<!-- Resource is treated as a static resource -->
<LinearGradientBrush x:Key="GradientBrush" EndPoint="0,0" StartPoint="0,1" >
<GradientStop Color="{StaticResource Color}" Offset="0" />
<GradientStop Color="{StaticResource Color}" Offset="1" />
</LinearGradientBrush>
</ResourceDictionary>
<!-- The lookup behavior is optimized to StaticResource.
A Storyboard therefore will be able to animate the Background resource.
-->
<Border Background="{DynamicResource GradientBrush}" />
If the resource that an element references is itself referencing at least one resource using DynamicResource, then the reference will remain dynamic and will prevent e.g., the Storyboard from being frozen and the animation won't work:
<ResourceDictionary>
<Color x:Key="Color">#000000</Color>
<!-- Resource is treated as a dynamic resource,
because it contains at least one DynamicResource reference.
-->
<LinearGradientBrush x:Key="GradientBrush" EndPoint="0,0" StartPoint="0,1" >
<GradientStop Color="{DynamicResource Color}" Offset="0" />
<GradientStop Color="{StaticResource Color}" Offset="1" />
</LinearGradientBrush>
</ResourceDictionary>
<!-- The lookup behavior is now DynamicResource and not optimized.
A Storyboard won't be able to animate the properties of the resource as it can't be frozen.
-->
<Border Background="{DynamicResource GradientBrush}" />
Another effect you ecounter is that all items have the same Background when you select a TabItem.
This is related to the way the XAML engine handles resources. Referenceing a resource using StaticResource, results in the resource being shared by default.
You have two solutions to fix this issue:
Declare each participating resource of the static reference as non-shared by setting the x:Shared attribute to false:
<ResourceDictionary>
<Color x:Key="Color"
x:Shared="False">#000000</Color>
<LinearGradientBrush x:Key="GradientBrush"
x:Shared="False"
EndPoint="0,0"
StartPoint="0,1" >
<GradientStop Color="{StaticResource Color}" Offset="0" />
<GradientStop Color="{StaticResource Color}" Offset="1" />
</LinearGradientBrush>
</ResourceDictionary>
<Border Background="{StaticResource GradientBrush}" />
Alternatively, define the animated resource as inline. This way each TabItem border will have its own/non-shared Brush resource:
<ResourceDictionary>
<Color x:Key="Color">#000000</Color>
</ResourceDictionary>
<Border>
<Border.Background>
<LinearGradientBrush EndPoint="0,0" StartPoint="0,1" >
<GradientStop Color="{StaticResource Color}" Offset="0" />
<GradientStop Color="{StaticResource Color}" Offset="1" />
</LinearGradientBrush>
</Border.Background>
</Border>
I'm trying to get to grips with ControlTemplates in WPF. I noticed that when you try to reference a templated parent's background color - the binding statement seems to be different for elipse Fill and elipse GradientStop. Can any one explain why this is.
This works...
<Ellipse RenderTransformOrigin=".5,.5" Fill="{TemplateBinding Background}">
This works...
<GradientStop Offset="0" Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Background.Color}"/>
This doesnt work - why is this?
<GradientStop Offset="0" Color="{TemplatedParent Background}"/>
This produces an error...
<GradientStop Offset="0" Color="{TemplatedParent Background.Color}"/>
This doesnt work...
<Ellipse RenderTransformOrigin=".5,.5" Fill="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Background.Color}">
The instance looks like this...
<Button Template="{StaticResource buttonTemplate1}"
Height="100" Width="100" FontSize="40"
Background="Violet" Foreground="Aquamarine"
Padding="0" Margin="6">Button 5</Button>
As mentioned in comments, you need to distinguish between Brush and Color type properties.
Brush-typed properties are used by controls, and include Fill, Stroke, and Background.
The most common use of Color is as a component of a Brush, either the color of a SolidColorBrush, or the color of a GradientStop of a LinearGradientBrush.
There are also some binding syntax errors in the examples you posted.
This doesnt work - why is this?
<GradientStop Offset="0" Color="{TemplatedParent Background}"/>
That's not a valid binding syntax. But assuming you meant TemplateBinding Background, then it's still not valid, because the target Color is a different type than the source Background (Brush).
This produces an error...
<GradientStop Offset="0" Color="{TemplatedParent Background.Color}"/>
Same issue as above, you mean TemplateBinding instead of TemplatedParent. And, I believe that in any case TemplateBinding won't work for a nested property. You would need to write:
<GradientStop Offset="0" Color="{TemplateBinding
RelativeSource={RelativeSource TemplatedParent}, Path=Background.Color}" />
This doesnt work...
<Ellipse RenderTransformOrigin=".5,.5" Fill="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Background.Color}">
The syntax is correct here, but the types don't match -- the target is Brush, and the source is System.Color.
I have a ComboBox with a custom theme I wrote, and I get the error message "Cannot animate (0).(1) on an immutable object." This specifically happens when I set its selectedindex after the user selects one of the options in the combobox.
Doing some research online, I found that this is a common issue with databound items or dynamic resources. I'm not using any databound resources, but what I think is happening is since the combobox is collapsed, it tries to set the state of a button that doesn't exist. I narrowed it down to this code:
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="Border" Property="Background" Value="{DynamicResource spPressedStateBrush}" />
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Border" Property="Background" Value="{DynamicResource spOverStateBrush}" />
</Trigger>
</ControlTemplate.Triggers>
Which depends on these Dynamic Resources:
<LinearGradientBrush x:Key="spOverStateBrush" StartPoint="0,0" EndPoint="0,1">
<GradientStop Color="#2C8CBF" Offset="0" />
<GradientStop Color="#2793BF" Offset="0.5" />
<GradientStop Color="#2483BF" Offset="0.5001" />
<GradientStop Color="#2C8CBF" Offset="1" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="spPressedStateBrush" StartPoint="0,0" EndPoint="0,1">
<GradientStop Color="#0C6C9F" Offset="0" />
<GradientStop Color="#07739F" Offset="0.5" />
<GradientStop Color="#04639F" Offset="0.5001" />
<GradientStop Color="#0C6C9F" Offset="1" />
</LinearGradientBrush>
So I'm pretty sure those dynamic resources are the culprit, but how would I solve this problem?
After painstakingly trying to debug it by comparing the code to the original Control Template, I figured out that transporting all of the resources that my control uses into the file itself, and replacing all DynamicResources with StaticResources and that fixed the bug I was having.
Be sure that both this two (spOverStateBrush or spPressedStateBrush) Brushes are not used in different place in your code.
In order to be animatable, the Background Brush (spOverStateBrush or spPressedStateBrush) of the Border must be mutable, which the default value isn't.
If you use one of these two Brushes in another place, You should assign a new LinearGradientBrush before animating something like this code:
LinearGradientBrush gradient = new LinearGradientBrush();
gradient.StartPoint = new Point( 0.5, 0 );
gradient.EndPoint = new Point( 0.5, 1 );
gradient.GradientStops.Add(new GradientStop(Colors.Black, 0));
gradient.GradientStops.Add(new GradientStop(Color.FromArgb(100,69,87,186), 1));
Border.Background = gradient;
Ok so here's the problem. Am trying to figure out how to make this work:
Consider the following ControlTemplate for creating a Custom Button:
<ControlTemplate x:Key ="cButton" TargetType="{x:Type Button}">
<!--Styles-->
<Grid x:Name="bkg">
<Grid.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
<GradientStop Color="{TemplateBinding Background}" Offset="0.5"/><!-- Error! -->
<GradientStop Color="White" Offset="1.0"/>
</LinearGradientBrush>
</Grid.Background>
<ContentPresenter
TextBlock.FontSize="80"
HorizontalAlignment="Center"
VerticalAlignment="Center"
ContentSource="Content" />
</Grid>
<!--Triggers-->
<ControlTemplate.Triggers>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="bkg" Property="Background" Value="White"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
This Control Template forms part of this script and as you can see I am trying to get the background colour from the button declaration outlined in the main grid.
<Grid>
<Grid.Resources>
<ControlTemplate x:Key ="cButton" TargetType="{x:Type Button}">
<!--Styles-->
<Grid x:Name="bkg">
<Grid.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
<GradientStop Color="{TemplateBinding Background}" Offset="0.5"/><!-- Error! -->
<GradientStop Color="White" Offset="1.0"/>
</LinearGradientBrush>
</Grid.Background>
<ContentPresenter
TextBlock.FontSize="80"
HorizontalAlignment="Center"
VerticalAlignment="Center"
ContentSource="Content" />
</Grid>
<!--Triggers-->
<ControlTemplate.Triggers>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="bkg" Property="Background" Value="White"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Grid.Resources>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions >
<Button Name="btnIn" Grid.Column="0" Content="IN" Background="Green" Foreground="White" Template="{StaticResource cButton}"/>
<Button Name="btnOut" Grid.Column="1" Content="OUT" Background="Red" Foreground="White" Template="{StaticResource cButton}" />
</Grid>
Ok now Main question is this one..
Question 1: Why is the line marked with an Error Comment in the ControlTemplate of the button NOT retrieving the background colour using the templatebinding? Had I used a solid colour it would have worked fine so I see no reason why it should not work in this manner. And please provide reason why this is happening.
The following are still a bit unclear and I don't know if they may be related to the problem, if someone can clear them out it would be great.
Question 2: What is the difference between these two TargetType values "Button" and "{x:Type Button}". I know that they are a typeof equivalent but is there any difference between the two? I read MSDN but the real difference is not that clear.
Question 3: When would I use x:Name and when would I use Name ? The difference again is unclear.
Question 4: What does x:Static do?
I think that your template does not work correctly because Background property is a Brush (class). And you try bind it to Color (struct)
UPD
You can use simple converter like this:
public class BrushToColorConverter: IValueConverter{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
SolidColorBrush b = value as SolidColorBrush;
if (b != null)
{
return b.Color;
}
return null;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
Add it to resources:
<wpfApplication1:BrushToColorConverter x:Key="btcConv"/>
And modify your style:
<Grid.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
<GradientStop Color="{Binding Path=Background, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource btcConv}}" Offset="0.5"/>
<GradientStop Color="White" Offset="1.0"/>
</LinearGradientBrush>
</Grid.Background>
Or you can use binding like this (if you sure that Background is SolidColorBrush):
<GradientStop Color="{Binding Path=Background.Color, RelativeSource={RelativeSource TemplatedParent}}" Offset="0.5"/>
I get this error
'disable_glow' name cannot be found in the name scope of 'System.Windows.Controls.ControlTemplate'.
when trying to do this:
Application's resources:
<LinearGradientBrush Opacity="0.0" StartPoint="0,0"
EndPoint="0,1" x:Key="disable_glow" x:Name="disable_glow">
<GradientStop Offset="0.0" Color="#4D4D4D" />
<GradientStop Offset="0.1" Color="#404040" />
<GradientStop Offset="1.0" Color="#2E2E2E" />
</LinearGradientBrush>
in here:
Same place, in the ControlTemplate of the control Style:
<Border CornerRadius="4">
<Border.Background>
<DrawingBrush>
<DrawingBrush.Drawing>
<DrawingGroup>
<GeometryDrawing Brush="{StaticResource disable_glow}">
<GeometryDrawing.Geometry>
<RectangleGeometry Rect="0,0,1,1"/>
</GeometryDrawing.Geometry>
</GeometryDrawing>
...
When I use either StaticResource or DynamicResource keyword I get the same error.
So how to use it correctly?
You don't need to set the x:Name attribute on your LinearGradientBrush, if it's in a ResourceDictionary (i.e. a Resources collection). You just need to set x:Key to be able to access it.
The error you are getting would not be produced by the Brush="{StaticResource disable_glow}" code. If the resources wasn't found it would say something like "Resource not found". It sounds like you are/were trying to access it by name.
You would need to ensure that your LinearGradientBrush is defined before your ControlTemplate.