WPF: не удается установить свойства в свойствах элементарных элементов

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>

Дает мне следующую ошибку:
Невозможно установить свойства в элементах свойств.

Если я использую:

<l:CustomPanel>  
    <l:CustomPanel.Caption>
        <TextBlock Text="Caption text" FontSize="18" Foreground="White" /> 
    </l:CustomPanel.Caption>
</l:CustomPanel>

My TextBlock отображается отлично, но он вложен в другой текстовый блок, как будто он даже кажется, что он добавлен за пределы свойства Caption:

<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>

Как вы, возможно, уже догадались, мне нужен мой код, чтобы установить свойство Caption из XAML на пользовательской панели, если это возможно.

Я тоже пробовал тот же код с DependencyProperty, но безрезультатно.

Итак, любой, кто может помочь мне с этой проблемой?

Ответ 1

Я могу объяснить, что происходит не так и как его исправить.

Во-первых,

<l:CustomPanel>
  <l:CustomPanel.Caption Text="Caption text" FontSize="18" Foreground="White" />

- простая синтаксическая ошибка. Синтаксис <l:CustomPanel.Caption> не принимает атрибуты XML - значение свойства должно находиться внутри элемента.

Это правильный синтаксис элемента свойства:

<l:CustomPanel>    
  <l:CustomPanel.Caption>  
    <TextBlock Text="Caption text" FontSize="18" Foreground="White" />   
  </l:CustomPanel.Caption>  
</l:CustomPanel>

а

  • Синтаксис элемента свойства работает только с DependencyProperties (поэтому он не работал с вашим свойством CLR) и
  • Синтаксис элемента свойства всегда отличает атрибут ContentPropertyAttribity типа свойства

Так как TextBlock имеет [ContentPropertyAttribute ( "Inlines" )], синтаксис элемента свойства пытается добавить TextBlock в коллекцию Inlines.

Решение прост: объявите свое свойство как DependencyProperty типа UIElement вместо типа TextBlock. Это имеет дополнительное преимущество, не ограничивая отображение содержимого только текстовым блоком. Если вы действительно хотите ограничить его только TextBlock, вы можете использовать обратный вызов проверки.

public UIElement Content { get { ...
public static readonly DependencyProperty ContentProperty = ...

Ответ 2

Просто получил не идеальное обходное решение от моего коллеги. Он включает объявление свойства Caption в качестве ресурса, например:

<Page.Resources>
    <TextBlock x:Key="test" Text="Caption text" FontSize="18" Foreground="White" />
</Page.Resources>

<l:CustomPanel Caption="{StaticResource test}" />

Я все еще хотел бы знать, почему я не могу использовать два предыдущих варианта, поэтому, если кто-нибудь знает, ответьте.:)

Ответ 3

Кажется, вы можете получить эту ошибку (по крайней мере, в Silverlight 4 и 5), если вы укажете пространство имен в элементе. Например:

<Path>
    <MapLayer.Position xmlns="clr-namespace:Microsoft.Maps.MapControl">
        ...

В этом случае MapLayer.Position является присоединенным свойством. Похоже, что синтаксический анализатор Silverlight требует, чтобы пространство имен определялось с помощью префикса:

<Path xmlns:map="clr-namespace:Microsoft.Maps.MapControl">
    <map:MapLayer.Position>
        ...