rscarson rscarson - 1 month ago 10
C# Question

DependencyProperty only binds sometimes and is reported as a missing property in the designer

I have a very strange problem with a user control's dependency properties.

It compiles, but a text appears in expected way. The color property works for the first 2 uses (endColor and progressColor), but does work in the text's foreground color.

Even though it should apply the correct color, the value of endColor.Color, it simply returns black - the default value.

Although it compiles and should work, the designer reports: "it can't find the property and marks my XAML as invalid".

I have restarted VS and deleted the designer shadowcache, but to no avail.

I use it like this is in the main window:

<local:HoverButton x:Name="cancelButton" Text="Cancel" Color="Crimson" />


Here is my xaml:

<UserControl x:Class="gbtis.HoverButton" x:Name="hoverButton"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:gbtis"
mc:Ignorable="d">
<Grid>
<Border x:Name="borderBox" BorderThickness="4" CornerRadius="2">
<Border.BorderBrush>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop x:Name="endColor" Color="{Binding Path=Color, ElementName=hoverButton, UpdateSourceTrigger=PropertyChanged}" Offset="0"/>

<GradientStop x:Name="progressColor" Color="{Binding Path=Color, ElementName=hoverButton, UpdateSourceTrigger=PropertyChanged}" Offset="1"/>
<GradientStop x:Name="progressBlack" Color="Black" Offset="1"/>

<GradientStop Color="Black" Offset="1"/>
</LinearGradientBrush>
</Border.BorderBrush>
<Grid>
<Viewbox>
<TextBlock x:Name="textBox" Margin="2,0,2,0"
Foreground="{Binding Color, ElementName=hoverButton, UpdateSourceTrigger=PropertyChanged}"
Text="{Binding Text, ElementName=hoverButton, UpdateSourceTrigger=PropertyChanged}" />
</Viewbox>
</Grid>
</Border>
</Grid>
</UserControl>


And my control code:

public static readonly DependencyProperty ColorProperty = DependencyProperty.Register("Color", typeof(Color), typeof(HoverButton), new FrameworkPropertyMetadata(Colors.Black) { BindsTwoWayByDefault = true });
public Color Color {
get { return (Color)this.GetValue(ColorProperty); }
set { SetValueDp(ColorProperty, value); }
}

public event PropertyChangedEventHandler PropertyChanged;
void SetValueDp(DependencyProperty property, object value,
[System.Runtime.CompilerServices.CallerMemberName] String p = null) {
SetValue(property, value);
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(p));
}


UPDATE:

I removed the event I had used to try and force an update and gave the textbox a solidcolorbrush. Now the properties seem to work.

However... The designer still shows them as not recognized or innaccessible

Answer

The reason why the specified binding is not working is because you're binding TextBlock.Foreground property, which is of type Brush, to your HoverButton.Color property, which is of type Color, and the framework is not able to convert a Color to a Brush.

So in order to fix this you either need to provide a converter through Binding.Converter property to do the job, or provide a brush and make it use the value of the HoverButton.Color. In this case I think the brush you're looking for is a SolidColorBrush:

<TextBlock (...)>
    <TextBlock.Foreground>
        <SolidColorBrush Color="{Binding Color, ElementName=hoverButton, UpdateSourceTrigger=PropertyChanged}" />
    </TextBlock.Foreground>
</TextBlock>

Note though that if you go with the second solution, making the binding TwoWay is pretty much pointless.

Comments