WPF:无法在属性元素上设置属性怪异

Wil*_*lly 10 .net c# wpf xaml properties

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>
Run Code Online (Sandbox Code Playgroud)

给我以下错误:
无法在属性元素上设置属性.

如果我使用:

<l:CustomPanel>  
    <l:CustomPanel.Caption>
        <TextBlock Text="Caption text" FontSize="18" Foreground="White" /> 
    </l:CustomPanel.Caption>
</l:CustomPanel>
Run Code Online (Sandbox Code Playgroud)

我的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>
Run Code Online (Sandbox Code Playgroud)

正如您可能已经猜到的那样,我希望我的代码可以在自定义面板上设置我的Caption属性,如果可能的话.

我也尝试使用DependencyProperty相同的代码无济于事.

那么,有谁可以帮我解决这个问题呢?

Ray*_*rns 13

我可以解释出现了什么问题以及如何解决它.

第一,

<l:CustomPanel>
  <l:CustomPanel.Caption Text="Caption text" FontSize="18" Foreground="White" />
Run Code Online (Sandbox Code Playgroud)

是一个简单的语法错误.该<l:CustomPanel.Caption>语法不接受XML属性-属性值必须是在元素中.

这是正确的属性元素语法:

<l:CustomPanel>    
  <l:CustomPanel.Caption>  
    <TextBlock Text="Caption text" FontSize="18" Foreground="White" />   
  </l:CustomPanel.Caption>  
</l:CustomPanel>
Run Code Online (Sandbox Code Playgroud)

但:

  1. 属性元素语法仅适用于DependencyProperties(因此它不适用于您的CLR属性)和
  2. Property元素语法始终遵循属性类型的ContentPropertyAttribute

由于TextBlock具有[ContentPropertyAttribute("Inlines")],因此属性元素语法正在尝试将TextBlock添加到Inlines集合中.

解决方案很简单:将属性声明为UIElement类型的DependencyProperty,而不是类型TextBlock.这具有额外的优点,即不将内容的显示限制为仅仅TextBlock.如果您确实想将其限制为TextBlock,则可以使用验证回调.

public UIElement Content { get { ...
public static readonly DependencyProperty ContentProperty = ...
Run Code Online (Sandbox Code Playgroud)