WPF: Cannot set properties on property elements weirdness
Solution 1
I can explain what is going wrong and how to fix it.
First,
<l:CustomPanel>
<l:CustomPanel.Caption Text="Caption text" FontSize="18" Foreground="White" />
is a simple syntax error. The <l:CustomPanel.Caption>
syntax does not accept XML attributes - the property value must be within the element.
This is proper property element syntax:
<l:CustomPanel>
<l:CustomPanel.Caption>
<TextBlock Text="Caption text" FontSize="18" Foreground="White" />
</l:CustomPanel.Caption>
</l:CustomPanel>
but:
- Property element syntax works only with DependencyProperties (so it didn't work with your CLR property) and
- Property element syntax always honors the ContentPropertyAttribute of the property type
Since TextBlock has a [ContentPropertyAttribute("Inlines")], the property element syntax is trying to add the TextBlock to the Inlines collection.
The solution is simple: Declare your property as a DependencyProperty of type UIElement instead of type TextBlock. This has the additional advantage of not restricting the display of content to just a TextBlock. If you really do want to restrict it to just a TextBlock, you can use a validation callback.
public UIElement Content { get { ...
public static readonly DependencyProperty ContentProperty = ...
Solution 2
Just got a non-ideal workaround from a colleague of mine. It involves declaring the Caption property as a resource like:
<Page.Resources>
<TextBlock x:Key="test" Text="Caption text" FontSize="18" Foreground="White" />
</Page.Resources>
<l:CustomPanel Caption="{StaticResource test}" />
I'd still like to know why I can't use the two previous options, so if anyone knows please answer. :)
Comments
-
Willy almost 2 years
private TextBlock _caption = new TextBlock(); public TextBlock Caption { get { return _caption; } set { _caption = value; } } <l:CustomPanel> <l:CustomPanel.Caption Text="Caption text" FontSize="18" Foreground="White" /> </l:CustomPanel>
Gives me the following error:
Cannot set properties on property elements.If I use:
<l:CustomPanel> <l:CustomPanel.Caption> <TextBlock Text="Caption text" FontSize="18" Foreground="White" /> </l:CustomPanel.Caption> </l:CustomPanel>
My TextBlock shows up fine but it's nested inside another TextBlock like so, it even seems to add itself outside of the Caption property:
<l:CustomPanel> <l:CustomPanel.Caption> <TextBlock> <InlineUIContainer> <TextBlock Text="Caption text" FontSize="18" Foreground="White" /> </InlineUIContainer> </TextBlock> </l:CustomPanel.Caption> <TextBlock> <InlineUIContainer> <TextBlock Text="Caption text" FontSize="18" Foreground="White" /> </InlineUIContainer> </TextBlock> </l:CustomPanel>
As you might have already guessed, what i'd like my code to do is to set my Caption property from XAML on a custom panel, if this is possible.
I've also tried the same code with a DependencyProperty to no avail.
So, anyone that can help me with this problem?
-
Willy about 14 yearsThx Ray, that worked :) Although I didn't need it anymore, I might need it in the future though, so thank you for the clear explanation.
-
Glenn Maynard over 7 yearsExcept, how are you supposed to say <my.element xml:space="preserve">? Somebody didn't think this through, and blindly applied this to all attributes, even ones that don't belong to them.