境界線やその他の視覚的な装飾を含むスタイルを持つ ContentControl があります。コンテンツが折りたたまれたときにこれらの装飾が消えるようにしたいので、この場合は ContentControl の可視性を折りたたむように設定する必要があると考えました。ContentControl 装飾用に次のスタイルを取得しました。
<Style x:Key="DecoratedItem1" TargetType="{x:Type c:DecoratedItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type c:DecoratedItem}">
<StackPanel Orientation="Horizontal">
<Border BorderBrush="Black" BorderThickness="2" CornerRadius="2">
<StackPanel Orientation="Horizontal">
<Image Source="/Images/file.png"/>
<ContentPresenter Name="wContent"/>
</StackPanel>
</Border>
</StackPanel>
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding ElementName=wContent, Path=Content.Visibility}" Value="Collapsed">
<DataTrigger.Setters>
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger.Setters>
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
DecoratedItem クラスは、この問題には関係のない追加の DependencyProperties を持つ ContentControl の単なるサブクラスです。必要に応じてコードを追加できるサブクラスが既にあることに注意してください。
これは、ContentControl のコンテンツが UIElement の場合に機能しますが、コンテンツが DataTemplate によって生成された場合、Visibility プロパティが見つからないというエラーが発生します。
<!-- works -->
<c:DecoratedItem Style="{StaticResource DecoratedItem1}">
<TextBlock Text="ABC" Visibility="Collapsed"/>
</c:DecoratedItem>
<!-- doesn't work -->
<c:DecoratedItem Style="{StaticResource DecoratedItem1}" Content="ABC">
<c:DecoratedItem.Resources>
<DataTemplate DataType="{x:Type clr:String}">
<TextBlock Text="{Binding}" Visibility="Collapsed"/>
</DataTemplate>
</c:DecoratedItem.Resources>
</c:DecoratedItem>
デバッグ出力ウィンドウに表示される 2 番目のケースのエラーは次のとおりです。
System.Windows.Data Error: 40 : BindingExpression path error:
'Visibility' property not found on 'object' ''String' (HashCode=-885832486)'.
BindingExpression:Path=Content.Visibility;
DataItem='ContentPresenter' (Name='wContent');
target element is 'DecoratedItem' (Name='');
target property is 'NoTarget' (type 'Object')
これが起こる理由は理解できますが、自分のスタイルを希望どおりに修正する方法がわかりません。必要に応じて、DecoratedItem サブクラスにヘルパー コードを追加してもかまいません。これを修正する方法はありますか?
[編集1]
提案された回答に関するいくつかの説明:
Content が常に UIElement であることを強制することはできません。結局のところ、これはモデル ビューの設計であり、もちろん、例を大幅に単純化しました。実際のプロジェクトでは、コンテンツは DataContext から選択されたモデルであり、いくつかの異なるタイプにすることができ、DataTemplate はそのモデルのプレゼンテーションを構築します。一部の DataTemplates は (モデルの状態に応じて) 表示するものがないと判断し、Visibility を Collapsed に切り替えます。その情報をデコレーティングコンテナに伝播したいと思います。上記の例は、動機ではなく問題を示しているだけです。申し訳ありません。
[編集2]
モデルについて詳しく知ることが問題にどのように役立つかはわかりませんが、ここで説明します。Content フィールドのデータは、多くのものになる可能性があるため、あまり共通点がありません。この DecoratedItem は、一部のフォームに表示されるアイテムに共通の視覚的スタイルを与えるために再利用可能であると想定されています。コンテンツは、無効になっている場合に DataTemplate によって折りたたまれる作業項目のようなものです。他の種類のコンテンツは不完全で、折りたたまれている可能性があります。もちろん、他の種類は決して崩壊しないかもしれません。
ただし、データ モデルは問題とあまり関係がないことに注意してください。問題は、展開されたコンテンツ要素の可視性に対してバインドする方法です (サブクラスを介してバインド可能な方法で公開した後)。