Silverlight по умолчанию содержимое ContentPresenter - PullRequest
5 голосов
/ 28 января 2011

Почему это не работает?

В generic.xaml для настраиваемого элемента управления:

В стиле, применяемом к настраиваемому элементу управления ...

<Setter Property="ChromeContent">
  <Setter.Value>
    <Grid />
  </Setter.Value>
</Setter>

...

Позже в шаблоне элемента управления ...

<ContentPresenter Grid.Column="0" 
     x:Name="ChromeContentPresenter" 
     Content="{TemplateBinding ChromeContent}" />

Вот свойство зависимости для ChromeContent ...

public Object ChromeContent
{
  get { return (Object)GetValue(ChromeContentProperty); }
  set { SetValue(ChromeContentProperty, value); }
}
public static readonly DependencyProperty ChromeContentProperty =
    DependencyProperty.Register("ChromeContent", typeof(Object), 
    typeof(casPopup), null);

Как видите, для этого нужен любой предмет.Я попытался изменить его на сетку, но это не помогло.

Выдает эту ошибку (из javascript): _Не удалось присвоить свойству 'System.Windows.Controls.ContentPresenter.Content'

Как ни странно, следующее будет работать нормально, если я удалю Grid из установщика и просто использую текст:

<Setter Property="ChromeContent" Value="DEFAULT" />

Кроме того, это также будет работать из метода OnApplyTemplate в классе элемента управления:

  Grid g = new Grid();
  g.Width = 100;
  g.Height = 25;
  g.Background = new SolidColorBrush(Colors.LightGray);
  ChromeContent = g;

Мне трудно понять, что мешает стандартному содержимому сетки, определенной в generic.xaml, работать.У кого-нибудь есть знания по этому вопросу?

Большое спасибо заранее за вашу помощь!

1 Ответ

6 голосов
/ 28 января 2011

Это проблема: -

<Setter Property="ChromeContent">
  <Setter.Value>
    <Grid />
  </Setter.Value>
</Setter>

Вы не должны включать UIElement непосредственно в словарь ресурсов или в качестве значения стиля. Вы можете увидеть стиль как своего рода дескриптор, но это не так. Значения в стиле представляют собой созданные экземпляры объектов, которые они содержат. Ваш стиль содержит один экземпляр Grid. Всякий раз, когда этот стиль используется для присвоения свойству ChromeContent, он пытается использовать один и тот же единственный экземпляр Grid.

A UIElement может быть только потомком одного из родителей. Что произойдет, если два экземпляра вашего контроля были построены? Будет (если позволят вам серебряный свет) попытаться назначить один и тот же один экземпляр Grid для обоих элементов управления.

Это одна из причин для таких шаблонов, как ControlTemplate и DataTemplate. Разметка внутри них вызывается при каждом использовании шаблона, а не при первом разборе Xaml.

Редактировать

Чтобы ответить на дополнительный вопрос, по умолчанию необходимо указать другое свойство типа DataTemplate: -

<Setter Property="ChromeContentTemplate">
  <Setter.Value>
    <DataTemplate>
      <Grid />
    </DataTemplate>
  </Setter.Value>
</Setter>

Свойство: -

public Object ChromeContentTemplate
{
  get { return (DataTemplate)GetValue(ChromeContentTemplateProperty); }
  set { SetValue(ChromeContentTemplateProperty, value); }
}

public static readonly DependencyProperty ChromeContentTemplateProperty=
    DependencyProperty.Register("ChromeContentTemplate", typeof(DataTemplate), 
    typeof(casPopup), null);

Шаблон управления: -

<ContentPresenter Grid.Column="0" 
     x:Name="ChromeContentPresenter" 
     Content="{TemplateBinding ChromeContent}"
     ContentTemplate="{TemplateBinding ChromeContentTemplate" />
...