2017-01-05 2 views
0

Je suis coincé avec le problème suivant:Application modèle à un ContentControl en fonction du type de données objet lié

Je dois faire un ContentControl personnalisé qui, lorsqu'ils ne sont pas concentrés aurait un DataTemplate par défaut avec un TextBlock intérieur, mais lorsque Focused (iether par Mouse ou Keyboard) devrait pouvoir présenter un autre DataTemplate approprié basé sur le type de contenu. Pour un exemple, disons que si le type de contenu est String alors un DataTemplate avec un TextBox devrait être présenté, si c'est DateTime - puis un DateTimePicker, et ainsi de suite.

Je sais qu'il existe un moyen de fournir différents DataTemplates en fonction de Focused/NotFocused pour ListBoxItems, je l'ai implémenté en appliquant un Style avec des Triggers. Mais dans ce cas, je suis coincé. Je l'ai essayé avec Style, mais sans succès.

Voici ce que je suis venu avec à ce jour:

Thèmes/generix.xaml pour le contrôle gadget qui est juste hérité d'un ContentControl:

<ControlTemplate x:Key="String"> 
    <Border BorderBrush="Green" BorderThickness="1"> 
     <TextBlock Text="{Binding Path=Content, RelativeSource={RelativeSource TemplatedParent}}"></TextBlock> 
    </Border> 
</ControlTemplate> 
<ControlTemplate x:Key="Int32"> 
    <Border BorderBrush="Blue" BorderThickness="1"> 
     <TextBlock Text="{Binding Path=Content, RelativeSource={RelativeSource TemplatedParent}}"></TextBlock> 
    </Border> 
</ControlTemplate> 
<ControlTemplate x:Key="Base"> 
    <Border BorderBrush="Yellow" BorderThickness="1"> 
     <TextBlock Text="{Binding Path=Content, RelativeSource={RelativeSource TemplatedParent}}"></TextBlock> 
    </Border> 
</ControlTemplate> 
<local:DTC x:Key="DataTypeConverter"></local:DTC> 
<Style TargetType="{x:Type local:Gadget}"> 
    <Style.Triggers> 
     <DataTrigger Binding="{Binding Content, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type local:Gadget}}, Converter={StaticResource DataTypeConverter}}" Value="String}"> 
      <Setter Property="Template" Value="{StaticResource String}"></Setter> 
     </DataTrigger> 
     <DataTrigger Binding="{Binding Content, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type local:Gadget}}, Converter={StaticResource DataTypeConverter}}" Value="Int32}"> 
      <Setter Property="Template" Value="{StaticResource Int32}"></Setter> 
     </DataTrigger> 
    </Style.Triggers> 
    <Setter Property="Padding" 
      Value="2" /> 
    <Setter Property="Template" Value="{StaticResource Base}"> </Setter> 
</Style> 

Le backend de contrôle gadget a un seul constructeur statique :

static Gadget() 
    { 
     DefaultStyleKeyProperty.OverrideMetadata(typeof(Gadget), 
        new FrameworkPropertyMetadata(typeof(Gadget))); 

    } 

C'est le TestClass:

public class TestClass 
{ 
    public TestClass(string one, string two) 
    { 
     One = one; 
     Two = two; 
     Three = count++; 
    } 

    static int count = 0; 

    public string One { get; set; } = "One1"; 
    public string Two { get; set; } = "Two2"; 
    public int Three { get; set; } 
} 

C'est le valueConverter:

public class DTC : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, 
     CultureInfo culture) 
    { 
     return value.GetType(); 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, 
     CultureInfo culture) 
    { 
     throw new NotImplementedException(); 
    } 
} 

Voici comment j'essaie de l'utiliser dans une zone de liste

<ListBox Name="lstBox" Margin="10,10,172,40"> 
     <ListBox.ItemTemplate> 
      <DataTemplate> 
       <StackPanel Orientation="Horizontal"> 
        <local:Gadget Content="{Binding Path=One}"></local:Gadget> 
        <local:Gadget Content="{Binding Path=Two}"></local:Gadget> 
        <local:Gadget Content="{Binding Path=Three}"></local:Gadget> 
       </StackPanel> 
      </DataTemplate> 
     </ListBox.ItemTemplate> 
    </ListBox> 

J'ai cherché partout, mais je ne suis pas non plus formuler bien ma question, ou peut-être que personne n'a jamais eu besoin de ça ...

J'apprécierai vraiment toutes les suggestions à ce sujet!

Merci beaucoup d'avance!

EDIT

Afin de faire la suggestion du travail mm8 j'ai modifié l'objet DTC pour revenir au lieu de type String. Le code extrait ci-dessus est corrigé en conséquence.

+0

Avez-vous essayé ''? –

+0

Cependant, c'est le genre de choses que vous faites habituellement avec un DataTemplate. –

Répondre

0

se lient à la propriété Contenu de {RelativeSource Self} et retourner le type réel de la méthode Convert du convertisseur:

<Style TargetType="{x:Type local:Gadget}" xmlns:s="clr-namespace:System;assembly=mscorlib"> 
    <Setter Property="Padding" Value="2" /> 
    <Setter Property="Template" Value="{StaticResource Base}"></Setter> 
    <Style.Triggers> 
     <DataTrigger Binding="{Binding Content, RelativeSource={RelativeSource Self}, Converter={StaticResource DataTypeConverter}}" 
        Value="{x:Type s:String}"> 
      <Setter Property="Template" Value="{StaticResource String}"></Setter> 
     </DataTrigger> 
     <DataTrigger Binding="{Binding Content, RelativeSource={RelativeSource Self}, Converter={StaticResource DataTypeConverter}}" 
        Value="{x:Type s:Int32}"> 
      <Setter Property="Template" Value="{StaticResource Int32}"></Setter> 
     </DataTrigger> 
    </Style.Triggers> 
</Style> 

public class DTC : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     return value.GetType(); 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     throw new NotImplementedException(); 
    } 
} 
+0

Merci beaucoup, ** mm8 **! Ça marche! Le style sélectionne ControlTemplate en fonction du type renvoyé. J'ai modifié le code de l'objet DTC (DataTypeConverter), dans mon message d'origine au lieu de l'objet Type réel, il a renvoyé une chaîne. Pour que votre suggestion fonctionne, j'ai corrigé DataTypeConverter pour renvoyer Type. – Intelso