2016-05-03 10 views
0

ContentControlを含むUserControlsの複数のレイヤーを持つことはできませんか?WPF ContentControl Content as ContentControl

派生した異なるモデルのビューを作成しようとしています。そのため、オブジェクトタイプごとにビューを再作成する必要がなくなり、代わりにContentControlまたはContentPresenterを使用して、ビューの残りの部分 "です。しかし、私はこの方法で一段階深くしか行くことができません。

ここでは簡単な例を示します(一部のxmlnsを削除しました)。私の場合は、はるかに複雑なビューで作業していて、複数の場所で重複したコードを削除しようとしています。

私はベースのUserControlを持って、我々はそれがContentControlにはUserControlLevel2と呼ばれ、次のユーザーコントロールに使用されます

namespace ContentControlNesting 
{ 
    public partial class UserControlLevel1 : UserControl 
    { 
     public UserControlLevel1() 
     { 
      InitializeComponent(); 
     } 

     public static readonly DependencyProperty ChildContentProperty = DependencyProperty.Register("ChildContent", typeof(UIElement), typeof(UserControlLevel1), new PropertyMetadata(null)); 

     public UIElement ChildContent 
     { 
      get { return (UIElement)GetValue(ChildContentProperty); } 
      set { SetValue(ChildContentProperty, value); } 
     } 
    } 
} 

のUserControl

で次のDependencyPropertyを持って

<UserControl x:Class="ContentControlNesting.UserControlLevel1" 
      x:Name="userControlLevel1" 
      xmlns:local="clr-namespace:ContentControlNesting"> 
    <StackPanel> 
     <TextBlock Text="UserControlLevel1ContentTop"/> 
     <ContentControl Content="{Binding ElementName=userControlLevel1, Path=ChildContent}"/> 
     <TextBlock Text="UserControlLevel2ContentBottom"/> 
    </StackPanel> 
</UserControl> 

をUserControlLevel1呼ぶことにします。このUserControlは正常に動作します。 UserControlLevel1ではなくUserControlLevel1内で正しく動作します。

<UserControl x:Class="ContentControlNesting.UserControlLevel2" 
      x:Name="userControlLevel2" 
      xmlns:local="clr-namespace:ContentControlNesting"> 
    <local:UserControlLevel1> 
     <local:UserControlLevel1.ChildContent> 
      <StackPanel> 
       <TextBlock Text="UserControlLevel2ContentTop"/> 
       <ContentControl Content="{Binding ElementName=userControlLevel2, Path=ChildContent}"/> 
       <TextBlock Text="UserControlLevel2ContentBottom"/> 
      </StackPanel> 
     </local:UserControlLevel1.ChildContent> 
    </local:UserControlLevel1> 
</UserControl> 

同様に、それが最初のように、このユーザーコントロール上のContentControlにするための単一のDependencyPropertyにしています。私はまた、DependencyPropertiesとは違った名前でこれを試しました。

namespace ContentControlNesting 
{ 
    public partial class UserControlLevel1 : UserControl 
    { 
     public UserControlLevel1() 
     { 
      InitializeComponent(); 
     } 

     public static readonly DependencyProperty ChildContentProperty = DependencyProperty.Register("ChildContent", typeof(UIElement), typeof(UserControlLevel1), new PropertyMetadata(null)); 

     public UIElement ChildContent 
     { 
      get { return (UIElement)GetValue(ChildContentProperty); } 
      set { SetValue(ChildContentProperty, value); } 
     } 
    } 
} 

さて、この時点ですべてが正常に動作しているようです。 UserControlLevel1のContentControl内に追加のコンテンツを追加し、UserControlLevel2 UserControl内に別のContentControlを追加しました。

問題は、UserControlまたはMainWindowの3番目の層を導入しようとするときです。 UserControlLevel2のContentControlに追加するものは表示されません。

<Window x:Class="ContentControlNesting.MainWindow" 
     xmlns:local="clr-namespace:ContentControlNesting" 
     Title="MainWindow" Height="200" Width="300"> 
    <local:UserControlLevel2> 
     <local:UserControlLevel2.ChildContent> 
      <StackPanel> 
       <TextBlock Text="Main Window Content Text"/> 
      </StackPanel> 
     </local:UserControlLevel2.ChildContent> 
    </local:UserControlLevel2> 
</Window> 

私はそれができないことをしようとしていますか?または、私はContentControlとDependencyPropertiesで何か問題があるのですか?私はこれを別のアプローチで見なければならないでしょうか?

+0

- stackoverflow.com/a/5758383/2777422を似ているが、別の質問に。ニーズは異なっていましたが、答えの1つの内容は当初正しい方向に向いていたようでした。 ControlTemplateを使用することをお勧めします。私の質問は、なぜこれで私は2レベル以上深く行くことができますか?最終的には、これは完璧な答えでもありません。私はIntellisenseのデータバインディングを緩めてしまい、上記のUserControlLevel1 Textbloxsのテキスト値を駆動するDependencyPropertiesを作成した後、ControlTemplateにデフォルト値が表示されません。 – Jeremy

答えて

0

可能です。システムはBindingElementNameを解決できません。ソリューションは、相対バインディングを使用することです。ただ、UserControlLevel2に次の行を交換し、あなたが行われています。私はこの答えにつまずい

<ContentControl Content="{Binding Path=ChildContent, RelativeSource={RelativeSource AncestorType={x:Type local:UserControlLevel2}}}"/> 
+0

これはうまくいくように見えますが、いくつかの注意点があります。ユーザーコントロールの複数のインスタンスが使用されている場合、最初はDesignerで更新されません。変更を表示するには、プロジェクト/ソリューションを再構築する必要があります。さらに、ユーザーコントロールの各ティアには、異なる名前のプロパティが必要です。私がレベル1とレベル2の両方に親戚ソースを追加すると、デザイン時にエラーが発生し、実行時に例外がスローされました。私はプロパティの名前を階層ごとにユニークに変更し、それはうまくいくと思われますが、変更を確認するために前述のように再構築を実行する必要があります。 – Jeremy

関連する問題