Currently I've hardcoded the property (DisplayName) of the DataContext object that should be shown. But normally you specify this path in the ComboBox itself with the property DisplayMemberPath. How can I use the value specified by DisplayMemberPath as the property to bind against in the content presenter?
<Style TargetType="{x:Type ComboBoxItem}">
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Border x:Name="ItemBorder"
Padding="2,0"
BorderThickness="1"
CornerRadius="3">
<ContentPresenter Content="{Binding DisplayName}"/>
</Border>
<ControlTemplate.Triggers>
<Trigger SourceName="ItemBorder" Property="IsMouseOver" Value="True">
<Setter TargetName="ItemBorder" Property="Background" Value="{StaticResource LightBlueBackgroundBrush}"/>
<Setter TargetName="ItemBorder" Property="BorderBrush" Value="{StaticResource LightBlueBackgroundBrush}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
For reference, here is my ComboBox style.
<Style TargetType="{x:Type ComboBox}">
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/>
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
<Setter Property="ScrollViewer.CanContentScroll" Value="true"/>
<Setter Property="Height" Value="22"/>
<Setter Property="Background" Value="White"/>
<Setter Property="BorderBrush" Value="{StaticResource MidGreyBorderStroke}"/>
<Setter Property="Border.CornerRadius" Value="3" />
<Setter Property="IsEditable" Value="False" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ComboBox}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="1"
CornerRadius="{TemplateBinding Border.CornerRadius}"
Width="{TemplateBinding Width}"
Height="{TemplateBinding Height}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<ContentPresenter x:Name="ReadOnlyContentPresenter"
Grid.Column="0"
Margin="5,0"
VerticalAlignment="Center"
HorizontalAlignment="Left"
Content="{TemplateBinding SelectionBoxItem}"
ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}"
ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}" />
<TextBox x:Name="PART_EditableTextBox"
Grid.Column="0"
Margin="5,0"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Visibility="Hidden"
IsReadOnly="{TemplateBinding IsReadOnly}" />
<Border Grid.Column="1"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="1,0,0,0"
Margin="0,2" />
<ToggleButton Grid.Column="2"
Margin="1,0"
Background="{TemplateBinding Background}"
VerticalAlignment="Center"
HorizontalAlignment="Right"
Focusable="False"
IsChecked="{Binding Path=IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
ClickMode="Press"
Style="{StaticResource ComboBoxToggleButton}"/>
<Popup x:Name="PART_Popup"
AllowsTransparency="True"
Placement="Bottom"
IsOpen="{TemplateBinding IsDropDownOpen}"
Focusable="False"
PopupAnimation="Fade"
SnapsToDevicePixels="True">
<Grid Background="Transparent"
MinWidth="{TemplateBinding ActualWidth}"
MaxHeight="{TemplateBinding MaxDropDownHeight}">
<Border x:Name="DropDownBorder"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="1"
CornerRadius="{TemplateBinding Border.CornerRadius}"
Margin="0,2,0,0">
<ScrollViewer Margin="6,0">
<StackPanel IsItemsHost="True"
KeyboardNavigation.DirectionalNavigation="Contained" />
</ScrollViewer>
</Border>
</Grid>
</Popup>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Opacity" Value=".65" />
</Trigger>
<Trigger Property="HasItems" Value="false">
<Setter TargetName="DropDownBorder" Property="MinHeight" Value="42"/>
</Trigger>
<Trigger Property="IsEditable" Value="True">
<Setter Property="IsTabStop" Value="false"/>
<Setter TargetName="PART_EditableTextBox" Property="Visibility" Value="Visible"/>
<Setter TargetName="ReadOnlyContentPresenter" Property="Visibility" Value="Hidden"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Well this is actually an interesting question that has quite an simple answer.
Short answer:
<ContentPresenter />
Long answer:
If you have overridden the ComboBoxItem
style but you still want to use DisplayMemberPath
from the ComboBox
you don't have to put anything into the Styles Content
binding as the Parent
(ComboBox) will resolve this for you. Because DisplayMemberPath
is just a string not the actual property, if you Bind to DisplayMemberPath
all your items will just show whatever value you put into DisplayMemberPath
So all you have to do is remove the Content
binding from the ComboBoxItem
Style
Example:
<Style TargetType="{x:Type ComboBoxItem}">
.............
<Border x:Name="ItemBorder" Padding="2,0" BorderThickness="1" CornerRadius="3">
<ContentPresenter /> <!-- no content binding -->
</Border>
Here is a simple example that shows this working
Xaml:
<Window x:Class="WpfApplication13.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" x:Name="UI" Width="343" Height="744.625" >
<Window.Resources>
<Style TargetType="{x:Type ComboBoxItem}">
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ComboBoxItem">
<Border x:Name="ItemBorder" Padding="2,0" BorderThickness="1" CornerRadius="3">
<ContentPresenter />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<StackPanel DataContext="{Binding ElementName=UI}">
<ComboBox ItemsSource="{Binding Items}" DisplayMemberPath="Name" HorizontalAlignment="Left" VerticalAlignment="Top" Width="120"/>
<ComboBox ItemsSource="{Binding Items}" DisplayMemberPath="State" HorizontalAlignment="Left" VerticalAlignment="Top" Width="120"/>
</StackPanel>
</Window>
Code:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
for (int i = 0; i < 50; i++)
{
Items.Add(new ComboBoxModel { Name = "Name" + i, State = "State" + i });
}
}
private ObservableCollection<ComboBoxModel> _items = new ObservableCollection<ComboBoxModel>();
public ObservableCollection<ComboBoxModel> Items
{
get { return _items; }
set { _items = value; }
}
}
public class ComboBoxModel
{
public string Name { get; set; }
public string State { get; set; }
}
Result:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With