简体   繁体   中英

WPF ComboBox Conditional ItemTemplate

I have a ComboBox Binded to a List of Possible values is the ViewModel.

<ComboBox ItemsSource="{Binding PossibleOperands}" SelectedValue="{Binding Operand, Mode=TwoWay}" VerticalAlignment="Center"  Foreground="Black"  FontSize="13" FontFamily="Calibri"  Height="23" Grid.Column="1" Margin="7,2,0,2"/>

For most values I want the display a simple string (in The example above, "Operand Name"), but for one of the values, I want to display a string + 2 comboBoxes.

Mockup: 在此处输入图片说明

使用MSDN中所述的ItemTemplateSelector

You can define a single ItemTemplate with a textblock and 2 combobox. Bind the Visibility of ComboBoxes with the required property. This way only for certain items the ComboBoxes will be visible.

I have done something like that before: Assuming you have a class like this: (for the ComboBox 's Content)

    public class Content
    {
      private String _Texty;
      public String Texty
      {
        get{return _Texty;}
        set { _Texty = value; }
      }
      public List<String> Comb1{get ; set;}
      public List<String> Comb2 { get; set; }
      public Content(string t, List<String> comb1, List<String> comb2)
      {
        Texty = "Some Text";
        Comb1 = comb1;
        Comb2 = comb2;
      } 
    }

You will need a Converter , defined in your xaml part like this:

    <utils:ContentToVisibleConverter x:Key="MyConverter" /> 

where utils is something like:

    xmlns:utils="clr-namespace:YOUR CONVERTER CLASS NAMESPACE"

So, define your Combobox like this in the xaml:

    <ComboBox x:Name="Combo" Margin="4" 
    Height="23" 
    Width="250"  ItemsSource="{Binding Collection}" >
        <ComboBox.ItemTemplate> 
            <DataTemplate> 
                <StackPanel Orientation="Horizontal" >   
                    <TextBlock Text="{Binding Texty}" Margin="4,0"/>

                    <Grid Margin="20 0 0 0">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition />
                            <ColumnDefinition />
                            <ColumnDefinition />
                            <ColumnDefinition />
                        </Grid.ColumnDefinitions>
                        <TextBlock Grid.Column="0" Text="Entity Type:" 
                                   Visibility="{Binding Path=Comb1, Converter={StaticResource MyConverter}}" />
                        <ComboBox  Grid.Column="1" ItemsSource="{Binding Comb1}" Width="80" Margin="4,0"
                                   Visibility="{Binding Path=Comb1, Converter={StaticResource MyConverter}}"/>
                        <TextBlock Grid.Column="2" Text="Entity:" 
                                   Visibility="{Binding Path=Comb2, Converter={StaticResource MyConverter}}"/>
                        <ComboBox  Grid.Column="3" ItemsSource="{Binding Comb2}" Width="80" Margin="4,0"
                                   Visibility="{Binding Path=Comb2, Converter={StaticResource MyConverter}}"/>
                    </Grid>

                </StackPanel> 
            </DataTemplate> 
        </ComboBox.ItemTemplate>
    </ComboBox>

Somewhere in my code, I use a Binding Collection this way:

    private ObservableCollection<Content> _Collection;
     public ObservableCollection<Content> Collection
     {
        get { return _Collection; }
        set { _Collection = value; NotifyPropertyChanged("Collection"); }
    }
    // Fill it like this:
      Collection = new ObservableCollection<Content>(); 
      Collection.Add(new Content("Some Stuff", null, null));
      Collection.Add(new Content("Some Stuff", null, null));
      Collection.Add(new Content("Some Stuff", null, null));
      Collection.Add(new Content("Some Stuff",
                       new List<String>() { "One", "Two" },
                       new List<String>() { "One", "Two" }));

Finally, I define a class for the converter it only contains:

    public class ContentToVisibleConverter : System.Windows.Markup.MarkupExtension, IValueConverter
   {
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        var s = value as List<string>;
        if (s != null)
            return s.Count > 0 ? Visibility.Visible : Visibility.Collapsed;
        else return Visibility.Collapsed;
    }
    public object ConvertBack(object value, Type targetType, object parameter,  System.Globalization.CultureInfo culture)
    {
        return null;
    }
    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        return this;
    }
  }

That's all, let me know if it worked for you.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM