Bezdepbonusu7Программирование: статьи и ответы

Вопрос

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

Автор вопроса: WillyОтветов: 3
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 безрезультатно.

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

propertieswpfxaml

Ответы

Ответ 1 · рейтинг 15 · Ray Burns

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

Первый,

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

Ответ 2 · рейтинг 2 · Willy

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

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

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

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

Ответ 3 · Drew Noakes

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

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы