Silverlight默认ContentPresenter内容

时间:2011-01-28 14:52:38

标签: silverlight custom-controls default contentpresenter

为什么这不起作用?

在自定义控件的 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'

奇怪的是,如果我从setter中删除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 个答案:

答案 0 :(得分:6)

这就是问题所在: -

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

您不应将UIElement直接包含在资源字典中或作为样式的值。您可能会将样式视为某种描述符,但事实并非如此。样式中的值是它们所持有的对象的构造实例。您的样式包含Grid的单个实例。每当使用该样式分配给ChromeContent属性时,它将尝试为网格提供相同的单个实例。

UIElement只能是父母一方的孩子。如果您的控件构建了两个实例,会发生什么?将(如果silverlight允许)尝试将Grid的单个实例分配给两个控件。

这是ControlTemplateDataTemplate等模板的一个原因。每次使用模板时都会调用这些标记,而不是在首次解析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" />