2011-02-02 41 views
11

ユーザーが依存プロパティに設定するモードに応じて、ユーザーコントロールをTextBlockと別のTextBlockまたはTextBlockとTextBoxに変更するユーザーコントロールを作成しようとしています。私は依存関係のプロパティが情報を取得していることを知っていますが、正しいテンプレートを設定しようとすると問題が発生します。何らかの理由で、テンプレートが正しくレンダリングされません。条件付きXAML(WPF)

XAML:

<UserControl x:Class="BookOrganizer.FlipBox" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     xmlns:my="clr-namespace:BookOrganizer" 
     mc:Ignorable="d" 
     d:DesignHeight="300" d:DesignWidth="300"> 
<StackPanel Orientation="Horizontal" Height="Auto" Width="Auto" > 
    <StackPanel.Resources> 
     <ContentControl x:Key="Box"> 
      <StackPanel Orientation="Horizontal"> 
       <TextBlock Text="{Binding Path=Title}" Height="Auto" Width="Auto" /> 
       <TextBox Text="{Binding Path=Text}" Height="Auto" Width="Auto" /> 
      </StackPanel> 
     </ContentControl> 
     <ContentControl x:Key="Block" Height="Auto" Width="Auto"> 
      <StackPanel Orientation="Horizontal" Height="Auto" Width="Auto"> 
       <TextBlock Text="{Binding Path=Title}" Height="Auto" Width="Auto" /> 
       <TextBlock Text="{Binding Path=Text}" Height="Auto" Width="Auto"/> 
      </StackPanel> 
     </ContentControl> 
    </StackPanel.Resources> 
    <ContentControl Template="{Binding Path=BoxMode}" /> 
</StackPanel> 

背後にあるコード:事前に

using System; 
using System.Windows; 
using System.Windows.Controls; 

namespace BookOrganizer 
{ 
    /// <summary> 
    /// Interaction logic for FlipBox.xaml 
    /// </summary> 
    public partial class FlipBox : UserControl 
    { 
     public static readonly DependencyProperty TitleProperty = DependencyProperty.Register(
     "Title", typeof(String), typeof(FlipBox), new PropertyMetadata("nothing")); 

     public static readonly DependencyProperty TextProperty = DependencyProperty.Register(
     "Text", typeof(String), typeof(FlipBox), new PropertyMetadata("nothing")); 

     public static readonly DependencyProperty BoxModeProperty = DependencyProperty.Register(
     "BoxMode", typeof(String), typeof(FlipBox), new PropertyMetadata("Box")); 

     public FlipBox() 
     { 
      InitializeComponent(); 
      this.DataContext = this; 
     } 

     public String Title 
     { 
      get { return (String)this.GetValue(TitleProperty); } 
      set { this.SetValue(TitleProperty, value); } 
     } 

     public String Text 
     { 
      get { return (String)this.GetValue(TextProperty); } 
      set { this.SetValue(TextProperty, value); } 
     } 

     public String BoxMode 
     { 
      get { return (String)this.GetValue(BoxModeProperty); } 
      set { this.SetValue(BoxModeProperty, value); } 
     } 

    } 
} 

感謝。ここで

+2

*「正しく表示されません」*を定義してください。期待されるアウトプットは何か、実際のアウトプットは何ですか? – Heinzi

+0

予想される出力は、テキストブロックと別のテキストブロック、またはテキストブロックとテキストボックスのいずれかになります。私が得るのは、円の中に赤い円と白いXが入っているか、何もない箱です。私はそれをどのように実行しようとするかに基づいています。 – chris

答えて

11

あなたは条件付きコントロールを作成する方法の例です。ここで

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

    #region Condition DP 

    public bool Condition 
    { 
     get { return (bool) GetValue(ConditionProperty); } 
     set { SetValue(ConditionProperty, value); } 
    } 

    public static readonly DependencyProperty ConditionProperty = 
     DependencyProperty.Register("Condition", typeof (bool), typeof (ConditionalControl), new UIPropertyMetadata(false)); 

    #endregion 

    #region TrueTemplate DP 

    public DataTemplate TrueTemplate 
    { 
     get { return (DataTemplate) GetValue(TrueTemplateProperty); } 
     set { SetValue(TrueTemplateProperty, value); } 
    } 

    public static readonly DependencyProperty TrueTemplateProperty = 
     DependencyProperty.Register("TrueTemplate", typeof (DataTemplate), typeof (ConditionalControl), new UIPropertyMetadata(null)); 

    #endregion 

    #region FalseTemplate DP 

    public DataTemplate FalseTemplate 
    { 
     get { return (DataTemplate) GetValue(FalseTemplateProperty); } 
     set { SetValue(FalseTemplateProperty, value); } 
    } 

    public static readonly DependencyProperty FalseTemplateProperty = 
     DependencyProperty.Register("FalseTemplate", typeof (DataTemplate), typeof (ConditionalControl), new UIPropertyMetadata(null)); 

    #endregion 
} 

は、それはあなたがあなたの中にThemes/Generic.xamlに置く必要があるスタイルだあるプロジェクト:

<Style TargetType="{x:Type Controls:ConditionalControl}"> 
    <Setter Property="Template"> 
     <Setter.Value> 
      <ControlTemplate TargetType="{x:Type Controls:ConditionalControl}"> 
       <Border Background="{TemplateBinding Background}" 
         BorderBrush="{TemplateBinding BorderBrush}" 
         BorderThickness="{TemplateBinding BorderThickness}"> 

        <Grid> 
         <ContentPresenter x:Name="FalseContentPresenter" 
              Content="{TemplateBinding DataContext}" 
              ContentTemplate="{TemplateBinding FalseTemplate}" /> 
        </Grid> 

       </Border> 
      </ControlTemplate> 
     </Setter.Value> 
    </Setter> 

    <Style.Triggers> 
     <Trigger Property="Condition" 
       Value="True"> 
      <Setter Property="Template"> 
       <Setter.Value> 
        <ControlTemplate TargetType="{x:Type Controls:ConditionalControl}"> 
         <Border Background="{TemplateBinding Background}" 
           BorderBrush="{TemplateBinding BorderBrush}" 
           BorderThickness="{TemplateBinding BorderThickness}"> 

          <Grid> 
           <ContentPresenter x:Name="TrueContentPresenter" 
                Content="{TemplateBinding DataContext}" 
                ContentTemplate="{TemplateBinding TrueTemplate}" /> 
          </Grid> 
         </Border> 
        </ControlTemplate> 
       </Setter.Value> 
      </Setter> 
     </Trigger> 
    </Style.Triggers> 
</Style> 
+0

非常にうまく動作します、ありがとう! – flq

0

あなたはおそらく必要があります。 IValueConverterを入力して、stringControlTemplateに変更します。それは、裸の文字列として渡されたときにリソースキーのルックアップを行いません。別のソリューションは、可視性を変更するStyleを使用することです:あなたは、テンプレートを設定するためにトリガーを使用することができます

<StackPanel Orientation="Horizontal"> 
    <TextBlock Text="{Binding Title}" /> 
    <TextBox Text="{Binding Text}"> 
      <TextBox.Style> 
       <Style TargetType="TextBox"> 
        <Setter Property="Visibility" Value="Collapsed" /> 
        <Style.Triggers> 
         <DataTrigger Binding="{Binding BoxMode}" Value="Box"> 
          <Setter Property="Visibility" Value="Visible" /> 
         </DataTrigger> 
        </Style.Triggers> 
       </Style> 
      </TextBox.Style> 
    </TextBox> 
    <TextBlock Text="{Binding Text}"> 
      <TextBlock.Style> 
       <Style TargetType="TextBlock"> 
        <Setter Property="Visibility" Value="Visible" /> 
        <Style.Triggers> 
         <DataTrigger Binding="{Binding BoxMode}" Value="Box"> 
          <Setter Property="Visibility" Value="Collapsed" /> 
         </DataTrigger> 
        </Style.Triggers> 
       </Style> 
      </TextBlock.Style> 
    </TextBlock> 
</StackPanel> 
13

。 UserControlのStackPanelをこれに置き換えてください。

<StackPanel Orientation="Horizontal" Height="Auto" Width="Auto" > 
     <ContentControl> 
     <ContentControl.Style> 
      <Style TargetType="{x:Type ContentControl}"> 
       <Style.Triggers> 
        <DataTrigger Binding="{Binding Path=BoxMode}" Value="Box"> 
        <Setter Property="Template"> 
         <Setter.Value> 
          <ControlTemplate> 
           <StackPanel Orientation="Horizontal" Height="Auto" Width="Auto"> 
           <TextBlock Text="{Binding Path=Title}" Height="Auto" Width="Auto" /> 
           <TextBlock Text="{Binding Path=Text}" Height="Auto" Width="Auto"/> 
           </StackPanel> 
          </ControlTemplate> 
         </Setter.Value> 
        </Setter> 
        </DataTrigger> 
        <DataTrigger Binding="{Binding Path=BoxMode}" Value="Block"> 
        <Setter Property="Template"> 
         <Setter.Value> 
          <ControlTemplate> 
           <StackPanel Orientation="Horizontal"> 
           <TextBlock Text="{Binding Path=Title}" Height="Auto" Width="Auto" /> 
           <TextBox Text="{Binding Path=Text}" Height="Auto" Width="Auto" /> 
           </StackPanel> 
          </ControlTemplate> 
         </Setter.Value> 
        </Setter> 
        </DataTrigger> 
       </Style.Triggers> 
      </Style> 
     </ContentControl.Style> 
     </ContentControl> 
    </StackPanel> 
+2

+1、バインディングは(デフォルトの)DataContextではなく、自分自身に供給されなければならないと思います。 – Jay

+0

サンプルプロジェクトでこれを試してみたところ、バインディングはそのまま動作していました。 –

+2

いいね! – Chris