'WPF ComboBox Multiple Columns
I am just wondering if there is a wpf combobox control that can contain multiple columns?
And if not, what XAML I need to use to achieve this?
I am just looking for a basic two column combobox if is possible,
Thanks
Solution 1:[1]
Please Refer these links for Multiple Column Combobox which is implemented by editing combox and comboboxitem Default template/style.
1)Link1
2)Link2
Xaml code : Please take a look at commented Trigger IsHighlighted in ComboboxItem style
<Grid>
<ComboBox Height="30" Margin="5" ItemsSource="{Binding}" HorizontalContentAlignment="Stretch">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Margin="2" Text="{Binding Name}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
<ComboBox.ItemContainerStyle>
<Style TargetType="{x:Type ComboBoxItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Grid x:Name="gd" TextElement.Foreground="Black">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Margin="5" Grid.Column="0" Text="{Binding Name}"/>
<TextBlock Margin="5" Grid.Column="1" Text="{Binding State}"/>
<TextBlock Margin="5" Grid.Column="2" Text="{Binding Population}"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="ComboBoxItem.IsSelected" Value="True">
<Setter TargetName="gd" Property="Background" Value="Gray"></Setter>
<Setter TargetName="gd" Property="TextElement.Foreground" Value="White"></Setter>
</Trigger>
<Trigger Property="ComboBoxItem.IsMouseOver" Value="True">
<Setter TargetName="gd" Property="Background" Value="Blue"></Setter>
<Setter TargetName="gd" Property="TextElement.Foreground" Value="White"></Setter>
</Trigger>
<!--IsHighlighted and IsMouseOver is showing same effect but IsHighlighted is used for showing logical focus( for understanding check using tab key)-->
<!--<Trigger Property="ComboBoxItem.IsHighlighted" Value="True">
<Setter TargetName="gd" Property="Background" Value="Yellow"></Setter>
<Setter TargetName="gd" Property="TextElement.Foreground" Value="Black"></Setter>
</Trigger>-->
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ComboBox.ItemContainerStyle>
</ComboBox>
</Grid>
c# code
public partial class MainWindow : Window
{
private ObservableCollection<City> cities = new ObservableCollection<City>();
public MainWindow()
{
InitializeComponent();
cities.Add(new City() { Name = "Mumbai", State = "Maharashtra", Population = 3000000 });
cities.Add(new City() { Name = "Pune", State = "Maharashtra", Population = 7000000 });
cities.Add(new City() { Name = "Nashik", State = "Maharashtra", Population = 65000 });
cities.Add(new City() { Name = "Aurangabad", State = "Maharashtra", Population = 5000000 });
DataContext = cities;
}
}
class City
{
public string State { get; set; }
public string Name { get; set; }
public int Population { get; set; }
}
Output
Solution 2:[2]
Because I found, Heena, that your Xaml does not provide selected dropped down items to be highlighted I modified your code as follows:
Xaml
<ComboBox Name="cbCities" Height="30" Margin="5" HorizontalContentAlignment="Left" HorizontalAlignment="Stretch" ItemsSource="{Binding}" >
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Margin="2" Text="{Binding Name}"/>
<TextBlock Margin="2" Text="{Binding State}"/>
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
<ComboBox.ItemContainerStyle>
<Style TargetType="{x:Type ComboBoxItem}">
<Setter Property="SnapsToDevicePixels" Value="True"/>
<Setter Property="OverridesDefaultStyle" Value="True"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ComboBoxItem}">
<Border Name="templateBorder" Padding="2" SnapsToDevicePixels="true">
<ContentPresenter>
<ContentPresenter.Content>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Margin="5" Grid.Column="0" Text="{Binding Name}"/>
<TextBlock Margin="5" Grid.Column="1" Text="{Binding State}"/>
<TextBlock Margin="5" Grid.Column="2" Text="{Binding Population}"/>
</Grid>
</ContentPresenter.Content>
</ContentPresenter>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsHighlighted" Value="True">
<Setter Property="Foreground" Value="{x:Static SystemColors.HighlightTextBrush}"/>
<Setter TargetName="templateBorder" Property="Background" Value="{x:Static SystemColors.HighlightBrush}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ComboBox.ItemContainerStyle>
</ComboBox>
C#
private void Window_Loaded(object sender, RoutedEventArgs e)
{
cities.Add(new City() { Name = "Boston", State = "MA", Population = 3000000 });
cities.Add(new City() { Name = "Los Angeles", State = "CA", Population = 7000000 });
cities.Add(new City() { Name = "Frederick", State = "MD", Population = 65000 });
cities.Add(new City() { Name = "Houston", State = "TX", Population = 5000000 });
cbCities.DataContext = cities;
}
class City
{
public string State { get; set; }
public string Name { get; set; }
public int Population { get; set; }
}
Output
Solution 3:[3]
I know im late but this is how you do it in a simplified way, After the
DataTemplate
tag you can put anything depending on how you want your lay out to look like.
<ComboBox.ItemTemplate>
<DataTemplate >
<StackPanel Orientation="Horizontal">
<TextBlock Foreground="{StaticResource ForegroundMainBrush}"
Margin="5 0"
FontFamily="{StaticResource LatoBold}"
VerticalAlignment="Center">
<Run Text="Code :" />
<Run Text="{Binding ActivityCode,Mode=OneWay}" />
</TextBlock>
<TextBlock Foreground="{StaticResource ForegroundDarkBrush}"
Margin="5 0"
Text="|"
FontFamily="{StaticResource LatoBold}"
VerticalAlignment="Center" />
<TextBlock Foreground="{StaticResource ForegroundMainBrush}"
Margin="5 0"
FontFamily="{StaticResource LatoBold}"
VerticalAlignment="Center">
<Run Text="Rate :" />
<Run Text="{Binding Rate,Mode=OneWay}" />
</TextBlock>
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
Result
Or Use a readonly property in your DataModel as shown on the code below and set your combobox DisplayMemberPath to
DisplayMemberPath="CodeRate"
public string ActivityCode { get; set; }
public string Rate { get; set; }
public string CodeRate => string.Format("Code: {0} | Rate:
{1}",ActivityCode,Rate);
Solution 4:[4]
I just use StackPanels in mine. Maybe kind of redundant per item, but it got me exactly the solution I wanted without getting too deep into things.
<ComboBox Name="cboTask">
<StackPanel Orientation="Horizontal">
<ComboBoxItem Name="someTask" Content="Doing Some Task" /><Button Name="cmdDetails" Content="..." />
</StackPanel>
</ComboBox>
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Community |
Solution 2 | Pollitzer |
Solution 3 | Heena |
Solution 4 | omJohn8372 |