Is it possible to dynamically choose which Control to render based on bindable attribute in Silverlight 4?

霸气de小男生 提交于 2020-01-13 19:27:14

问题


I have a ListBox with an ItemTemplate which renders a Grid with two columns. The first column is a TextBlock and the second is a ComboBox.

The idea is to present to the user a list of questions and a Combo from which the user can choose an answer. This works ok with this 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>

The reason for putting a TextBox inside the DataTemplate (in stead of TextBlock), is my first attempt on allowing the user to enter free text in addition to choosing from the dropdown. It kind of work, however, the TextBox is inside the ComboBox. That is not what I want.

Is it possible to have a "plain" TextBox render in stead of a ComboBox based upon some bindable attribute?

So that if an attribute InputType==FreeText the view is rendered with a TextBox and if the attribute is Inputtype==Combo it is rendered as above?

t.


回答1:


A simplistic solution to your specific problem is to include both and use a value converter on the Visibility property:-

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> { }

Then your Xaml can look like:-

    <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>

More sophisticated solutions would use a sub-class of ListBox and an override or PrepareContainerForItemOverride to allow variety of ItemTemplates to be assigned. However I think that would be overkill for this problem.



来源:https://stackoverflow.com/questions/3841943/is-it-possible-to-dynamically-choose-which-control-to-render-based-on-bindable-a

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!