So I’m trying to make a custom user control for a Windows Phone 7 application that I call a ColoredTextBlock. You can probably guess what it does.
Anyway, ColoredTextBlock contains a TextBlock which I want the user to be able to set the Text and Style for.
If I try just making a simple property that just passes through, such as:
public string Text
{
get { return Label.Text; }
set
{
Label.Text = value;
NotifyPropertyChanged("Text");
}
}
It causes a very cryptic ArgumentException. However if I set the input text, like:
<MyRepresentative:ColoredTextBlock Text="Some Text" BackgroundColor="Red" />
Everything works out exactly as I’d expect.
If on the other hand, I go with the more advanced route of using a Dependency property and binding the Inner TextBlock to this property, and then binding the external data to this property as well, nothing shows up.
public string Text
{
get { return (string)GetValue(TextProperty); }
set
{
SetValue(TextProperty, value);
NotifyPropertyChanged("Label");
}
}
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register("Text", typeof(string), typeof(ColoredTextBlock), null);
Again though, if I insert the text manually, the whole thing just works.
Here’s the xaml of my custom control:
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Class="MyRepresentative.ColoredTextBlock"
d:DesignWidth="456" d:DesignHeight="43"
DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Grid x:Name="LayoutRoot" Background="Transparent">
<Rectangle Stroke="Black">
<Rectangle.Fill>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="{Binding DimBackgroundColor}" Offset="0"/>
<GradientStop Color="{Binding BrightBackgroundColor}" Offset="0.85"/>
<GradientStop Color="{Binding BrightBackgroundColor}" Offset="0.15"/>
<GradientStop Color="{Binding DimBackgroundColor}" Offset="1"/>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
<TextBlock Text="{Binding Text}" Margin="5,0" d:LayoutOverrides="Width"/>
</Grid>
</UserControl>
I’ve been racking my brain on this for the better part of the day, and looking at so many different articles, and I’m certain at this point that I’m missing something small, but I just can’t find it.
UPDATE 1: After looking into it further, it appears that for some reason even though I set it up with bindings, it doesn’t appear that this is actually being set, at least as far as I can tell.
UPDATE 2: Based on the comment, you asked about making sure that my DataContext was set correctly. Ya, this was one of the first things I thought of. I have a lines below in my xaml.
<MyRepresentative:ColoredTextBlock Text="{Binding Title}" BackgroundColor="Red" />
<TextBlock Text="{Binding Title}" Style="{StaticResource PhoneTextLargeStyle}" />
So the first element doesn’t show up (at all), unless I change to something like Text="Some text". The second element works perfectly without error.
I ended up figuring out the answer to this problem myself, although it took me a while, and a bit of searching. The answer was actually inspired by this answer.
Answer:
Instead of binding to the root element using:
Such as I did in the example above:
Bind instead to the LayoutRoot, in this case, my Grid Element.
This can be done in your code behind, in the constructor, like I did here:
Explanation:
I don’t fully understand why this works to be honest, and if someone can explain it, please edit.
It seems to have to do with overriding existing bindings when you bind to the root element. As such, when you try to bind an external element to an element of this control, it will fail, because that binding isn’t accessible.
Hope that helps others who come across the same problem as me!