2010-10-01 13 views
2

J'ai un ListBox avec un ItemTemplate qui rend une Grille avec deux colonnes. La première colonne est un TextBlock et la seconde est un ComboBox.Est-il possible de choisir dynamiquement quel contrôle afficher en fonction de l'attribut bindable dans Silverlight 4?

L'idée est de présenter à l'utilisateur une liste de questions et un Combo à partir duquel l'utilisateur peut choisir une réponse. Cela fonctionne bien avec ce XAML:

 <ListBox x:Name="QAListBox" ScrollViewer.VerticalScrollBarVisibility="Auto" SelectedIndex="-1" 
      ItemsSource="{Binding Questions}" IsTabStop="True" TabIndex="5" 
      ScrollViewer.HorizontalScrollBarVisibility="Auto" Margin="10" BorderThickness="0"> 
      <ListBox.ItemTemplate> 
       <DataTemplate> 
        <Grid d:DesignWidth="931" d:DesignHeight="61" d:IsLocked="True" Margin="0"> 
         <Grid.ColumnDefinitions> 
          <ColumnDefinition Width=".80*" MinWidth="800"/> 
          <ColumnDefinition Width=".20*" MinWidth="200"/> 
         </Grid.ColumnDefinitions> 
         <TextBlock Text="{Binding Path=QuestionText}" Padding="10" FontSize="21.333" FontWeight="Bold" Margin="0" Grid.Column="0" d:IsLocked="True" /> 
         <ComboBox ItemsSource="{Binding Path=AnswerAlternative}" 
          SelectedValue="{Binding Path=QuestionsAndAnswers}" SelectedValuePath="AnswerAlternativeId" 
          FontSize="21.333" FontWeight="Bold" Grid.Column="1" Margin="60,0,0,0" d:IsLocked="True" SelectionChanged="ComboBox_SelectionChanged"> 
          <ComboBox.ItemTemplate> 
           <DataTemplate> 
            <TextBox Text="{Binding Path=AnswerText, Mode=TwoWay}" BorderThickness="0"> 
             <TextBox.Background> 
              <SolidColorBrush /> 
             </TextBox.Background> 
            </TextBox> 
           </DataTemplate> 
          </ComboBox.ItemTemplate> 
         </ComboBox> 
        </Grid> 
       </DataTemplate> 
      </ListBox.ItemTemplate> 
     </ListBox> 

La raison de mettre une zone de texte à l'intérieur du DataTemplate (au lieu de TextBlock), est ma première tentative permettant à l'utilisateur de saisir du texte libre en plus de choisir à partir de la liste déroulante. Ce genre de travail, cependant, le TextBox est dans le ComboBox. Ce n'est pas ce que je veux.

Est-il possible d'avoir un rendu TextBox "simple" à la place d'un ComboBox basé sur un attribut pouvant être lié? Donc, si un attribut InputType == FreeText est rendu avec un TextBox et si l'attribut est Inputtype == Combo, il est rendu comme ci-dessus?

t.

Répondre

1

Une solution simpliste à votre problème spécifique est d'inclure à la fois et d'utiliser un convertisseur de valeur sur la propriété de visibilité: -

public class EqualityToValueConverter<T> : IValueConverter 
{ 
    public T FalseValue { get; set; } 
    public T TrueValue { get; set; } 

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     if (value == null) 
      return FalseValue; 
     else 
      return value.ToString().Equals(parameter) ? TrueValue : FalseValue; 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     return value != null && value.Equals(TrueValue) ? parameter : null; 
    } 
} 

public class EqualityToVisibilityConverter : EqualityToValueConverter<Visibility> { } 

Ensuite, votre Xaml peut ressembler à: -

<ListBox x:Name="QAListBox" ScrollViewer.VerticalScrollBarVisibility="Auto" SelectedIndex="-1"  
     ItemsSource="{Binding Questions}" IsTabStop="True" TabIndex="5"  
     ScrollViewer.HorizontalScrollBarVisibility="Auto" Margin="10" BorderThickness="0"> 
     <ListBox.Resources> 
      <local:EqualityToVisibilityConverter x:Key="converter" 
      TrueValue="Visible" FalseValue="Collapsed" /> 
     </ListBox.Resources>  
     <ListBox.ItemTemplate>  
      <DataTemplate>  
       <Grid d:DesignWidth="931" d:DesignHeight="61" d:IsLocked="True" Margin="0">  
        <Grid.ColumnDefinitions>  
         <ColumnDefinition Width=".80*" MinWidth="800"/>  
         <ColumnDefinition Width=".20*" MinWidth="200"/>  
        </Grid.ColumnDefinitions>  
        <TextBlock Text="{Binding Path=QuestionText}" Padding="10" FontSize="21.333" FontWeight="Bold" Margin="0" Grid.Column="0" d:IsLocked="True" />  
        <ComboBox ItemsSource="{Binding Path=AnswerAlternative}"  
         SelectedValue="{Binding Path=QuestionsAndAnswers}" SelectedValuePath="AnswerAlternativeId"  
         FontSize="21.333" FontWeight="Bold" Grid.Column="1" Margin="60,0,0,0" d:IsLocked="True" SelectionChanged="ComboBox_SelectionChanged" 
         Visibility={Binding InputType, Converter={StaticResource converter}, ConverterParameter=Combo}">  
        <TextBox Text="{Binding Path=AnswerText, Mode=TwoWay}" Grid.Column="1" Margin="60,0,0,0" 
         Visibility={Binding InputType, Converter={StaticResource converter}, ConverterParameter=FreeText}">    
       </Grid>  
      </DataTemplate>  
     </ListBox.ItemTemplate>  
    </ListBox> 

Plus sophistiqué les solutions utiliseraient une sous-classe de ListBox et un remplacement ou PrepareContainerForItemOverride pour permettre l'attribution de divers ItemTemplates. Cependant, je pense que ce serait exagéré pour ce problème.