Reputation: 20471
Here is a simple custom control to illustrate my issue
public sealed class TestControl : Control
{
public static DependencyProperty TestColorProperty = DependencyProperty.Register("TestColor", typeof(Brush), typeof(TestControl), new PropertyMetadata(new SolidColorBrush(Colors.Blue)));
public Brush TestColor
{
get { return (Brush)GetValue(TestColorProperty); }
set { SetValue(TestColorProperty, value); }
}
public TestControl()
{
this.DefaultStyleKey = typeof(TestControl);
}
}
As you can see, it has a single Brush
dependency property, with a default value of Blue
(set in the PropertyMetaData
as shown above.
Here is the XAML for my control in Generic.xaml
<Style TargetType="local:TestControl">
<Setter Property="TestColor" Value="Red" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:TestControl">
<Border
Background="{TemplateBinding TestColor}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<TextBlock Text="TEST" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
As you can see, I set the TestColor
Brush dependency property to Red in a Style
setter - overriding the default value of Blue as declared in my PropertyMetaData.
Notice that my Border in my Template uses TemplateBinding
to set the background to the brush as discussed.
So what color do you think the border background gets set ? Red or Blue ?
The answer is neither.
If I set a breakpoint in my control somewhere where this value should be available (e.g. OnApplyTemplate
as an example) then the value is null, rather than Red (default) as expected. In fact I have set breakpoints at all of the lifecycle points in the control and the default value in ProprtyMetaData is never used.
Setting the value within the style does nothing either (it doesn't get set to Blue as per my style setter delaration. This suggests that the style setter is failing for SolidColorBrush
somehow.
However, this works
public BlankPage()
{
this.InitializeComponent();
testcont.TestColor = new SolidColorBrush(Colors.Orange);
}
and this works as well:
<Grid Background="{StaticResource ApplicationPageBackgroundBrush}">
<local:TestControl TestColor="Green" />
</Grid>
but TemplateBinding
just doesn't work, and this is important as Im trying to write re-useable custom controls.
Is this a bug ?
Dean
Upvotes: 5
Views: 2119
Reputation: 618
You can try the below code snippet to bind the TestColor,
Background="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TestColor}"
I hope it will be helpful.
Regards, Rex
Upvotes: 0
Reputation: 131
I have a working solution that uses a custom control, which in turn is placed multiple times into a user control (which is nice a reusable in my frames).
(in generic.xaml, recall I created a custom control)
<Style TargetType="local:myPad">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:myPad">
<Path Data="..." Height="60" Width="30" Fill="{TemplateBinding myPadColor}"/>
(in myPad.cs)
public sealed class myPad : Control
{
public myPad()
{
this.DefaultStyleKey = typeof(myPad);
}
public SolidColorBrush myPadColor
{
get { return (SolidColorBrush)GetValue(PadColorProperty); }
set { SetValue(PadColorProperty, value); }
}
public static readonly DependencyProperty PadColorProperty =
DependencyProperty.Register("myPadColor", typeof(SolidColorBrush), typeof(myPad), new PropertyMetadata(null));
}
in my user control, I then drop the template control and can have multiple "color" versions of the same...
<UserControl
x:Class=....
<Canvas Width="235" Height="235">
<local:myPad x:Name="thisPad" myPadColor="White">
...
I cut out much of the excess stuff (...), but I think you get the idea here. I also believe now too, that you can use yet another binding for myPadColor in the user control or in code-behind to get creative.
btw, i'm using VS2012 with SP3.. so perhaps things have been fixed now.
also, i'm pretty new to programming XAML, but at Tim Heuer's blog I found the right way to do the dependency property (thanks Tim!)
if you replace the (null) value in the propertymetadata value with your (new SolidColorBrush(Colors.Black)) you will get a default value in design mode.
:)
hope that helps.
Upvotes: 0
Reputation: 21
Seems it isn't yet fixed. If you develop something like custom button and PointerOver effect is just lighter background, a trick that works is to have invisible PointerOverVisual with white background on top of the content. Then PointerOver animation will make it slightly visible. That's what I use:
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="PointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Opacity" Storyboard.TargetName="pointerOverVisual">
<DiscreteObjectKeyFrame KeyTime="0" Value="0.15"/>
</ObjectAnimationUsingKeyFrames>
.......
<Border x:Name="Border" BorderThickness="0" Background="{TemplateBinding Background}" Margin="3">
content here
</Border>
<Rectangle x:Name="pointerOverVisual" Fill="White" Opacity="0" Margin="3"/>
<Rectangle x:Name="FocusVisualWhite" IsHitTestVisible="False" Opacity="0" StrokeDashOffset="1.5" StrokeEndLineCap="Square" Stroke="{StaticResource FocusVisualWhiteStrokeThemeBrush}" StrokeDashArray="1,1"/>
<Rectangle x:Name="FocusVisualBlack" IsHitTestVisible="False" Opacity="0" StrokeDashOffset="0.5" StrokeEndLineCap="Square" Stroke="{StaticResource FocusVisualBlackStrokeThemeBrush}" StrokeDashArray="1,1"/>
Upvotes: 0
Reputation: 691
Personally, I think it's a bug somewhere in xaml parser. Try something like this, it should work:
<Setter Property="SelectedDayBrush">
<Setter.Value>
<SolidColorBrush>#7F7F7F7F</SolidColorBrush>
</Setter.Value>
</Setter>
<Setter Property="SelectedDayBrush">
<Setter.Value>
<SolidColorBrush Color="Orange"/>
</Setter.Value>
</Setter>
Upvotes: 0
Reputation: 4311
this is an issue we're looking to address. In the mean time, set it up like this:
<SolidColorBrush x:Key="DefaultTestColorBrush">Red</SolidColorBrush>
and then in your template:
<Setter Property="TestColor" Value="{StaticResource DefaultTestColorBrush}" />
Then you should be able to clear this hurdle for now.
Upvotes: 0