首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

[WPF] Style 中設定 ToolTip 失敗原因深度解析與解決方案

     編輯:關於.NET

在 WPF 中嘗試透過 Style 設定 ToolTipService.ToolTip 並直接在 Setter.Value 放入 TextBlock 時,會拋出 XamlParseException:「無法將 'System.Windows.Controls.TextBlock' 類型的內容加入 'System.Object' 類型的物件」。本文從 BAML 解析機制深入分析根本原因,並提供正確解決方案。

問題重現

<TextBlock x:Name="textBlockContainer" Text="ABC" Margin="10">
  <TextBlock.Style>
    <Style TargetType="TextBlock">
      <Setter Property="ToolTipService.ToolTip">
        <Setter.Value>
          <TextBlock x:Name="tooltipBlock" Text="長文字內容" TextWrapping="Wrap" Width="70" />
        </Setter.Value>
      </Setter>
    </Style>
  </TextBlock.Style>
</TextBlock>

錯誤訊息:Cannot add content of type 'System.Windows.Controls.TextBlock' to an object of type 'System.Object'.

深度追蹤:BAML 解析機制

開啟 CLR Exception 中斷點後,可發現更早的內部異常:InvalidCastException: Unable to cast object of type 'System.Object' to type 'System.Reflection.MemberInfo'. 發生在 BamlRecordReader.SetPropertyValueToParent 方法。

WPF XAML 解析採自頂向下、由外而內方式。解析到 Setter.Value 時:

  1. 建立 TextBlock (tooltipBlock) 實例
  2. 嘗試將其設定給父節點 (Setter.Value) 的某個屬性
  3. Setter.Value 未賦值時回傳 DependencyProperty.UnsetValue(型別為 Object)
  4. 解析器嘗試尋找父節點的 ContentProperty、IList、IAddChild 等介面,均失敗
  5. 最終拋出「無法向 Object 添加子內容」異常

根本原因結論

WPF XAML 節點處理機制:實例化當前節點 → 設值給父節點屬性。若父節點屬性型別為 Object (如 UnsetValue),無法接受 UIElement 內容,故失敗。

正確解決方案:使用 StaticResource

將 ToolTip 內容定義為資源,再透過靜態資源引用:

<TextBlock x:Name="textBlockContainer" Text="ABC" Margin="10">
  <TextBlock.Resources>
    <TextBlock x:Key="toolTipBlock" Text="長文字內容" TextWrapping="Wrap" Width="70" />
  </TextBlock.Resources>
  <TextBlock.Style>
    <Style TargetType="TextBlock">
      <Setter Property="ToolTipService.ToolTip" Value="{StaticResource toolTipBlock}" />
    </Style>
  </TextBlock.Style>
</TextBlock>

此方式避開 Setter.Value 直接接受 UIElement 的問題,符合 WPF 資源解析機制。

補充說明

若直接在屬性元素語法設定 TextBlock.ToolTip(非透過 Style)則無此問題,因父節點為 ToolTip 物件,具備 Content 屬性可接受 UIElement。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved