I already search widely, but I can't find any solution to my case.
I have several ComboBox's at my project and I was searching for an AutoComplete solution, then I found a good one and applied in my project, I applied solution's style as well to all ComboBox in my project.
After that, SelectedItem stopped working, some one can help me ?
My Combobox:
<ComboBox Name="CbOwnerType" Grid.Column="1" Grid.Row="2" ItemsSource="{Binding Path=OwnerTypes, Mode=OneWay}" SelectedItem="{Binding Owner.OwnerType, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" SelectedValuePath="Id" DisplayMemberPath="Name" Margin="5,0,10,0" />
My style:
<Style TargetType="{x:Type ComboBox}">
<Setter Property="FocusVisualStyle" Value="{x:Null}" />
<Setter Property="Foreground" Value="Black" />
<Setter Property="FontWeight" Value="ExtraBold" />
<Setter Property="IsEditable" Value="False"/>
<Setter Property="IsSynchronizedWithCurrentItem" Value="False" />
<Setter Property="StaysOpenOnEdit" Value="True" />
<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="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ComboBox}">
<Grid>
<ToggleButton Name="ToggleButton" Template="{StaticResource ComboBoxToggleButton}" Grid.Column="2" Focusable="True" IsChecked="{Binding Path=IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" ClickMode="Press" BorderThickness="0" />
<ContentPresenter Name="ContentSite" IsHitTestVisible="False" Content="{TemplateBinding SelectionBoxItem}" ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}" ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}" Margin="5,0,20,0" VerticalAlignment="Center" HorizontalAlignment="Left" />
<TextBox x:Name="PART_EditableTextBox" Style="{x:Null}" Template="{StaticResource ComboBoxTextBox}" HorizontalAlignment="Left" VerticalAlignment="Bottom" Margin="3,3,23,3" Focusable="True" Background="Transparent" Visibility="Hidden" IsReadOnly="{TemplateBinding IsReadOnly}" />
<Popup Name="Popup" Placement="Bottom" IsOpen="{TemplateBinding IsDropDownOpen}" AllowsTransparency="True" Focusable="False" PopupAnimation="Slide">
<Themes:SystemDropShadowChrome Margin="4,6,4,6" CornerRadius="4">
<Grid Name="DropDown" SnapsToDevicePixels="True" MinWidth="{TemplateBinding ActualWidth}" MaxHeight="{TemplateBinding MaxDropDownHeight}">
<Border x:Name="DropDownBorder" Background="{StaticResource WindowBackgroundBrush}" BorderThickness="1" BorderBrush="{StaticResource SolidBorderBrush}" />
<ScrollViewer Margin="4,6,4,6" SnapsToDevicePixels="True">
<ItemsPresenter />
</ScrollViewer>
</Grid>
</Themes:SystemDropShadowChrome>
</Popup>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="HasItems" Value="false">
<Setter TargetName="DropDownBorder" Property="MinHeight" Value="95"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="{StaticResource DisabledForegroundBrush}"/>
</Trigger>
<Trigger Property="IsGrouping" Value="true">
<Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
</Trigger>
<Trigger SourceName="Popup" Property="Popup.AllowsTransparency" Value="true">
<Setter TargetName="DropDownBorder" Property="CornerRadius" Value="4"/>
<Setter TargetName="DropDownBorder" Property="Margin" Value="0,2,0,0"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
UPDATE
My ToggleButton
<ControlTemplate x:Key="ComboBoxToggleButton" TargetType="{x:Type ToggleButton}" >
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="20" />
</Grid.ColumnDefinitions>
<Border x:Name="Border" Grid.ColumnSpan="2" BorderBrush="{StaticResource LabPetsStandardColor}" BorderThickness="1" CornerRadius="5" />
<Border Grid.Column="0" Margin="1" Background="Transparent" BorderBrush="{StaticResource NormalBorderBrush}" BorderThickness="0" CornerRadius="5,0,0,5" />
<Path x:Name="Arrow" Grid.Column="1" HorizontalAlignment="Center" VerticalAlignment="Center" Data="M 0 0 L 4 4 L 8 0 Z">
<Path.Fill>
<SolidColorBrush Color="Black" />
</Path.Fill>
</Path>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="ToggleButton.IsMouseOver" Value="true">
<Setter TargetName="Border" Property="Background" Value="{StaticResource LabPetsStandardColor}" />
</Trigger>
<Trigger Property="ToggleButton.IsChecked" Value="true">
<Setter TargetName="Border" Property="Background" Value="{StaticResource LabPetsPressedStandardColor}" />
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter TargetName="Border" Property="Background" Value="{StaticResource DisabledBackgroundBrush}" />
<Setter TargetName="Border" Property="BorderBrush" Value="{StaticResource DisabledBorderBrush}" />
<Setter Property="Foreground" Value="{StaticResource DisabledForegroundBrush}"/>
<Setter TargetName="Arrow" Property="Fill" Value="{StaticResource DisabledForegroundBrush}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
My TextBox
<Style x:Key="ComboBoxTextBox" TargetType="{x:Type TextBox}">
<Setter Property="OverridesDefaultStyle" Value="True" />
<Setter Property="AllowDrop" Value="True" />
<Setter Property="MinWidth" Value="0" />
<Setter Property="MinHeight" Value="0" />
<Setter Property="FocusVisualStyle" Value="{x:Null}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<ScrollViewer HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden" Background="#00FFFFFF" Name="PART_ContentHost" Focusable="False" VerticalAlignment="Center" VerticalContentAlignment="Center" Margin="0">
<ScrollViewer.Style>
<Style TargetType="ScrollViewer">
<Setter Property="OverridesDefaultStyle" Value="True" />
</Style>
</ScrollViewer.Style>
</ScrollViewer>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Some, please, can help me ?
UPDATE 2
Found a hack, not the perfect solution, but kind of works...
If I insert property SelectedValue
and the value Owner.OwnerTypeId
, it works like a charm... But, it's right this?
My Combobox now:
<ComboBox Name="CbOwnerType" Grid.Column="1" Grid.Row="2" ItemsSource="{Binding Path=OwnerTypes, Mode=OneWay}" SelectedItem="{Binding Owner.OwnerType}" SelectedValue="{Binding Owner.OwnerTypeId}" SelectedValuePath="Id" DisplayMemberPath="Name" Margin="5,0,10,0" />
This is a solution, not that I like it, but it's a solution...
Some one can answer why SelectedItem
isn't working as it should ?
Obs.: When I change the selection, SelectedItem
works, just doesn't work when I load my view.
UPDATE 3
Ok, it's worked like I said, but the problem is that WPF is hitting 4 times at my ViewModel, so I changed my ComboBox
a little:
<ComboBox Name="CbOwnerType" Grid.Column="1" Grid.Row="2" ItemsSource="{Binding Path=OwnerTypes, Mode=OneWay}" SelectedItem="{Binding Owner.OwnerType}" SelectedValue="{Binding Owner.OwnerTypeId, Mode=OneTime}" SelectedValuePath="Id" DisplayMemberPath="Name" Margin="5,0,10,0" />
So, now, WPF just search the OwnerTypeId
and when I change an item, WPF just hits 2 times.
UPDATE 4
Ok, another strange finding...
In another ComboBox, with the same properties, except SelectedValue
, it's working perfect... I can't understand what is happening.
UPDATE 5
Sorry about that, I forgot to post my models.
Model Owner:
public class Owner
{
public int Id { get; set; }
public int OwnerTypeId { get; set; }
public string Name { get; set; }
public string Address { get; set; }
public string FormatedPhone
{
get
{
if (this.Phone == null)
return string.Empty;
switch (this.Phone.Length)
{
case 11:
return Regex.Replace(this.Phone, @"(\d{2})(\d{4})(\d{4})", "($1) $2-$3");
case 12:
return Regex.Replace(this.Phone, @"(\d{2})(\d{5})(\d{4})", "($1) $2-$3");
default:
return this.Phone;
}
}
}
public string Phone { get; set; }
public string CellPhone { get; set; }
public string FormatedCellPhone
{
get
{
if (this.CellPhone == null)
return string.Empty;
switch (this.CellPhone.Length)
{
case 11:
return Regex.Replace(this.Phone, @"(\d{2})(\d{4})(\d{4})", "($1) $2-$3");
case 12:
return Regex.Replace(this.Phone, @"(\d{2})(\d{5})(\d{4})", "($1) $2-$3");
default:
return this.CellPhone;
}
}
}
public string Email { get; set; }
public virtual OwnerType OwnerType { get; set; }
public virtual ICollection<Animal> Animals { get; set; }
public Owner()
{
this.OwnerType = new OwnerType();
this.Animals = new List<Animal>();
this.ErrorList = new StringBuilder();
}
Model OwnerType:
public class OwnerType
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Owner> Owners { get; set; }
public OwnerType()
{
this.Owners = new List<Owner>();
}
}
You have to do a Template binding of selectedValue of comobox. Because you have overriden the control template and placed your own TextBlock to display the selected value. Now when the value is selected from the UI control Template takes care of displaying it. but it is not setting the value to the SelectedValue or SelectedItem.
Hope this helps you