2010-05-26 10 views
5

Ho una proprietà che è un tipo di dati di database (char, datetime, int, float ecc ...) e voglio cambiare il controllo usato per inserire un valore del tipo selezionato. Quindi per i valori di testo voglio un TextBox e per i valori di data voglio un DatePicker.Visualizza dinamicamente un controllo in base alla proprietà associata usando WPF

Un modo in cui ho pensato di farlo era quello di avere uno di ciascun controllo sul mio modulo e impostare il loro Visibility utilizzando un'implementazione IValueConverter appropriata. So che funzionerà, ma creerebbe molto codice e non mi sembra molto bello.

L'altro modo che ho pensato è stato quello di utilizzare un ContentPresenter e impostare il suo contenuto con un Style e DataTriggers ma non riesco a farlo funzionare.

<Style x:Key="TypedValueHelper" TargetType="{x:Type ContentPresenter}"> 
     <Style.Triggers> 
      <DataTrigger Binding="{Binding Path=DataType}" Value="Char"> 
       <Setter Property="Content" Value="???"/> 
      </DataTrigger> 
      <DataTrigger Binding="{Binding Path=DataType}" Value="Date"> 
       <Setter Property="Content" Value="???"/> 
      </DataTrigger> 
      <DataTrigger Binding="{Binding Path=DataType}" Value="Integer"> 
       <Setter Property="Content" Value="???"/> 
      </DataTrigger> 
     </Style.Triggers> 
    </Style> 

Se qualcuno può compilare il mio "???" o offrire una soluzione migliore, per favore.

risposta

10

Si potrebbe fare una combinazione di stile, con setter e DataTemplates. Fondamentalmente hai l'inizio per questo nel tuo codice, anche se non penso che ContentPresenter sia il controllo giusto per lo stile, dal momento che non ha un modello.

Possibili qualcosa di simile:

<Style x:Key="TypedValueHelper" TargetType="{x:Type ContentControl}"> 
     <Style.Triggers> 
      <DataTrigger Binding="{Binding Path=DataType}" Value="Char"> 
       <Setter Property="ContentTemplate"> 
        <Setter.Value> 
         <DataTemplate> 
          <TextBox Text="{Binding Path=.}" /> 
         </DataTemplate> 
        </Setter.Value> 
       </Setter> 
      </DataTrigger> 
      <DataTrigger Binding="{Binding Path=DataType}" Value="Integer"> 
       <Setter Property="ContentTemplate"> 
        <Setter.Value> 
         <DataTemplate> 
          <Slider Maximum="100" Minimum="0" Value="{Binding Path=.}" 
              Orientation="Horizontal" /> 
         </DataTemplate> 
        </Setter.Value> 
       </Setter> 
      </DataTrigger> 
     </Style.Triggers> 
    </Style> 

...

<ContentControl Content="{Binding MyValue}" 
         Style="{StaticResource TypedValueHelper}"> 
+0

Puoi condividere il tuo codice nella fase attuale? – ThomasAndersson

+0

Non sono sicuro di poter condividere il mio codice perché ci sono molte dipendenze. In effetti, il mio problema reale è un po 'più complicato di quello che ho lasciato intendere. Sono abbastanza sicuro che la soluzione funzionerà per me Ho appena avuto un problema in cui sto cercando di impostare il contenuto di ContentControl su {Binding} piuttosto che su {Binding MyValue}, il che significa che WPF carica la vista per il mio ViewModel nel controllo dei contenuti, e continua a ricorsivamente ... –

+0

Ah, capisco. Hai provato {Binding Path =.}? – ThomasAndersson

0

Vorrei esaminare DataTemplates. Per esempio:

<DataTemplate DataType="{x:Type local:Input}"> 
      <local:InputControl DataContext="{Binding}" /> 
</DataTemplate> 

<DataTemplate DataType="{x:Type data:VideoData}"> 
       <local:VideoControl DataContext="{Binding}"></local:VideoControl> 
</DataTemplate> 
+0

Non sono sicuro che ciò funzionerebbe per me poiché non sto utilizzando un vero 'Tipo' per effettuare la mia scelta di controllo, sto utilizzando un valore di enumerazione esposto come proprietà sul mio ViewModel. –

5

Mentre la soluzione di stile potrebbe funzionare, il modo corretto di implementare il comportamento contenuti dinamici sarebbe quella di utilizzare DataTemplates come suggerito Sdry . Tuttavia, si utilizzerà un'enumerazione per determinare quale DataTemplate utilizzare; che essenzialmente significa che vuoi mappare un singolo tipo a più DataTemplates. Questo problema è risolto dalla classe DataTemplateSelector, la descrizione che segue è retta dalla MSDN:


"In genere, si crea un DataTemplateSelector quando si dispone di più di un DataTemplate per lo stesso tipo di oggetti e si desidera fornire il vostro propria logica per scegliere un DataTemplate da applicare in base alle proprietà di ciascun oggetto dati. "


È il contenuto dinamico dovrebbe essere ospitato da un ContentControl come questo:

<ContentControl Content="{Binding Path=ReferenceToYourViewModel}" ContentTemplateSelector="{DynamicResource MyTemplateSelector}"/> 

L'attuazione di MyTemplateSelector:

public class MyTemplateSelector: DataTemplateSelector 
{ 
    public override DataTemplate SelectTemplate(object item, DependencyObject container) 
    { 
     FrameworkElement elem = container as FrameworkElement; 
     if(elem == null) 
     { 
      return null; 
     } 
     if (item == null || !(item is YourViewModel)) 
     { 
      throw new ApplicationException(); 
     } 
     if ((item as YourViewModel).DataType == DataType.Char) 
     { 
      return elem.FindResource("CharDataTemplate") as DataTemplate; 
     } 
     if ((item as YourViewModel).DataType == DataType.Date) 
     { 
      return elem.FindResource("DateDataTemplate") as DataTemplate; 
     } 
     if ((item as YourViewModel).DataType == DataType.Integer) 
     { 
      return elem.FindResource("IntegerDataTemplate") as DataTemplate; 
     } 
     throw new ApplicationException(); 
    } 
} 

Allora come ci si aspetterebbe, qui ci sono i DataTemplates da scegliere da:

<DataTemplate x:Key="CharDataTemplate" DataType="{x:Type YourViewModel}">Put Your Xaml Here</DataTemplate> 
    <DataTemplate x:Key="DateDataTemplate" DataType="{x:Type YourViewModel}">Put Your Xaml Here</DataTemplate> 
    <DataTemplate x:Key="IntegerDataTemplate" DataType="{x:Type YourViewModel}">Put Your Xaml Here</DataTemplate> 

Con questo, verrà scelto il DataTemplate appropriato in base alla proprietà DataType del View Model. Quale a mio parere è molto più pulito rispetto all'utilizzo di Visibilità o Stili.

Problemi correlati