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>

Мой TextBlock отображается нормально, но он вложен в другой 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 безрезультатно.

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


person Willy    schedule 12.10.2009    source источник


Ответы (3)


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

Первый,

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

но:

  1. Синтаксис элемента свойства работает только с DependencyProperties (поэтому он не работает с вашим свойством CLR) и
  2. Синтаксис элемента свойства всегда учитывает ContentPropertyAttribute типа свойства.

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

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

public UIElement Content { get { ...
public static readonly DependencyProperty ContentProperty = ...
person Ray Burns    schedule 12.05.2010
comment
Спасибо, Рэй, это сработало :) Хотя мне это больше не нужно, оно может понадобиться мне в будущем, так что спасибо за четкое объяснение. - person Willy; 17.05.2010
comment
Кроме того, как вы должны сказать ‹my.element xml:space=preserve›? Кто-то не продумал это и вслепую применил ко всем всем атрибутам, даже к тем, которые им не принадлежат. - person Glenn Maynard; 13.02.2017

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

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

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

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

person Willy    schedule 12.10.2009

Кажется, вы можете получить эту ошибку (по крайней мере, в 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>
        ...
person Drew Noakes    schedule 08.12.2011