2016-08-31 3 views
0

非常に柔軟なカスタムコントロールを作成しようとしています。私はExpanderContentDependencyプロパティにUserControlをバインドできるように達成しようとしている柔軟性、スニペットの背後にあるコード:カスタムコントロールのコンテンツにUserControlをバインドする方法

public partial class ChartBar : UserControl 
{ 
    public UIElement ExpanderContent 
    { 
     get { return (UIElement)GetValue(ExpanderContentProperty); } 
     set { SetValue(ExpanderContentProperty, value); } 
    } 

    // Using a DependencyProperty as the backing store for ExpanderContent. This enables animation, styling, binding, etc... 
    public static readonly DependencyProperty ExpanderContentProperty = 
     DependencyProperty.Register("ExpanderContent", typeof(UIElement), typeof(ChartBar), new PropertyMetadata(null, OnExpanderContentChanged)); 

    private static void OnExpanderContentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     //throw new NotImplementedException(); 
    } 
    . 
    . 
    . 

私はXAMLでContentPresenterを使用して試してみましたが、それは動作しません。私は明らかにボタンで埋めることができ、それは動作しますが、これはバインディングを介して動的コンテンツを破ります。さらに混乱何

<Expander x:Name="expander" Header="" VerticalAlignment="Top" d:LayoutOverrides="Width" Style="{DynamicResource ExpanderStyle1}"> 
    <ContentPresenter Content="{Binding ExpanderContent, ElementName=TestControlWithContent}" /> 
    <!--<WrapPanel HorizontalAlignment="Center" > 
     <Button Content="A" Style="{DynamicResource ButtonStyle1}" /> 
     <Button Content="B" Style="{DynamicResource ButtonStyle1}" /> 
     <Button Content="C" Style="{DynamicResource ButtonStyle1}" /> 
     <Button Content="D" Style="{DynamicResource ButtonStyle1}" /> 
     <Button Content="E" Style="{DynamicResource ButtonStyle1}" /> 
     <Button Content="F" Style="{DynamicResource ButtonStyle1}" /> 
    </WrapPanel>--> 
</Expander> 

は私が

// ChartBarParent is the name of the custom control set in XAML 
ChartBarParent.Content = new TestControlWithContent(); 

を行うことができますし、それは同様にコールバックを発射するように動作します。

最終的には、UIElementは依存関係プロパティであり、ContentPresenterこれを行うには正しい方法を使用していますか?

+1

[ユーザーコントロールにコンテンツを追加する方法](http://stackoverflow.com/q/10427133/1997232)。 – Sinatr

+0

私はそのリンクを見てきましたが、ソリューションはtypeof(オブジェクト)を使用していましたが、これは私が達成したいものではありません。私はUIElementまたはFrameworkElementを使いたいと思っていました。私は何かが欠けていますか(非常に可能です)? – Jason

+0

'ContentPresenter'は' ControlTemplate'で使われることを意図しています。そのコンテンツを 'Content'プロパティをバインドするのではなく、その' ContentSource'プロパティをテンプレート化された親のプロパティの名前( 'ContentSource' 'はデフォルト値の' 'Content" 'を持っています。なぜなら、あなたはしばしば属性のないものをドロップすることができ、それは魔法のように何を意味するのですか?その特定の使用法が、あなたがやっていることには当てはまらない場合は、代わりに@ibebbsが提案して 'ContentControl'を使用してください。 –

答えて

0

これはどのようにこれを行うのですか。それはSecondaryContent(どちらか一方がUI使用)のもの(下の「使用法」の2番目の例のようなもの)、または暗黙的なDataTemplateのビューモデルに依存しています。私は簡単にSecondaryDataTemplateSelectorプロパティを追加して、消費者にテンプレートの作成方法をより明示的に制御させることができます。

ChartBar.cs

public class ChartBar : ContentControl 
{ 
    static ChartBar() 
    { 
     DefaultStyleKeyProperty.OverrideMetadata(typeof(ChartBar), 
      new FrameworkPropertyMetadata(typeof(ChartBar))); 
    } 

    // Rather than ExpanderContent, we're inheriting ContentControl.Content for the 
    // main control content. 

    #region SecondaryContent Property 
    public Object SecondaryContent 
    { 
     get { return (Object)GetValue(SecondaryContentProperty); } 
     set { SetValue(SecondaryContentProperty, value); } 
    } 

    public static readonly DependencyProperty SecondaryContentProperty = 
     DependencyProperty.Register("SecondaryContent", typeof(Object), typeof(ChartBar), 
      new PropertyMetadata(null)); 
    #endregion SecondaryContent Property 

    #region IsExpanded Property 
    // This is optional. I just know I'd end up wanting it. 
    public bool IsExpanded 
    { 
     get { return (bool)GetValue(IsExpandedProperty); } 
     set { SetValue(IsExpandedProperty, value); } 
    } 

    public static readonly DependencyProperty IsExpandedProperty = 
     DependencyProperty.Register("IsExpanded", typeof(bool), typeof(ChartBar), 
      new PropertyMetadata(false)); 
    #endregion IsExpanded Property 
} 

Themes/Generic.xaml、または他の<Application.Resources>内App.xaml、またはどちらか一方に含まれ、いくつかの他の.xamlリソースディクショナリ。

<ControlTemplate x:Key="ChartBarDefaultTemplate" TargetType="local:ChartBar"> 
    <!-- 
    Use Binding/RelativeSource TemplatedParent on IsExpanded so it updates both ways, 
    or remove that attribute/binding if you're not bothering with the IsExpanded DP. 
    --> 
    <Expander 
     x:Name="expander" 
     Header="" 
     VerticalAlignment="Top" 
     Style="{DynamicResource ExpanderStyle1}" 
     IsExpanded="{Binding IsExpanded, RelativeSource={RelativeSource TemplatedParent}}" 
     > 
     <StackPanel Orientation="Vertical"> 
      <ContentPresenter /> 
      <ContentControl 
       Content="{TemplateBinding SecondaryContent}" 
       /> 
     </StackPanel> 
    </Expander> 
</ControlTemplate> 

<Style TargetType="local:ChartBar"> 
    <Setter 
     Property="Template" 
     Value="{StaticResource ChartBarDefaultTemplate}" 
     /> 
</Style> 

使用法:

<StackPanel Orientation="Vertical" > 
    <!-- Control content --> 
    <local:ChartBar SecondaryContent="Secondary Content One"> 
     <StackPanel Orientation="Vertical"> 
      <Label>Chart Bar</Label> 
      <Ellipse Height="30" Width="60" Fill="GreenYellow" Opacity="0.2" /> 
      <Label>Other stuff, etc. etc.</Label> 
     </StackPanel> 
    </local:ChartBar> 

    <!-- Templated viewmodel content --> 
    <local:ChartBar Content="{Binding RandomViewModelProperty}" IsExpanded="True"> 
     <local:ChartBar.ContentTemplate> 
      <DataTemplate> 
       <Label Background="Beige" Content="{Binding}" Margin="20" /> 
      </DataTemplate> 
     </local:ChartBar.ContentTemplate> 
     <local:ChartBar.SecondaryContent> 
      <ComboBox> 
       <TextBlock Text="One" /> 
       <TextBlock Text="Two" /> 
       <TextBlock Text="Three" /> 
      </ComboBox> 
     </local:ChartBar.SecondaryContent> 
    </local:ChartBar> 
</StackPanel> 
+0

オプションAは私が達成しようとしているもののはるかに多くです。ボタンA〜Fは、単にエクスパンダが正しく動作するようにするためのプレースホルダでした。これらのプレースホルダは、 "UserControl"(対応するビューモデルを持つビュー)を使用して置き換えられます。空の ''は私の心配です。 – Jason

+0

@ Jasonそのセカンダリビュー/ビューモデルのコンテンツは毎回同じですか、それともそれをパラメータ化しますか? –

+0

ビューモデルは、このカスタムエクスパンダが接続されているもの(OHLCチャート、インジケータペインなど)に基づいてIoCを介して動的に解決されます。これは、さまざまなコンテンツを持つさまざまなユーザーコントロールをホストするため、できるだけ柔軟に展開するためです。 – Jason

1

ContentPresenterをContentControlに変更してみてください。

さらに、UserControlをDataTemplateにラップし、ContentControl.Contentプロパティを使用してデータコンテキストをフローできるContentControl.ContentTemplateとして設定できます。

+0

私はそれを試してみましょう。ありがとう。 – Jason

+0

「ContentPresenter」または「ContentControl」を使用しても問題はありませんでしたが、バインディングをどちらかと一緒に使用できるようになりましたが、バインドされたコンテンツは表示されませんでした。 – Jason

関連する問題