WPF Editable Combobox does not change SelectedValue while typing - wpf

I defined a Combobox whose SelectedValue is binded to a property on the view model VM.SelectedServiceTypeId
<ComboBox Name="ServiceTypeComboBox"
IsEditable="True"
Grid.Row="1"
Grid.Column="1"
Margin="5"
DisplayMemberPath="ServiceTypeName"
ItemsSource="{Binding ServiceTypes,Mode=TwoWay}"
SelectedValue="{Binding SelectedServiceTypeId, Mode=TwoWay}"
SelectedValuePath="ServiceTypeId"
Loaded="ServiceTypeComboBox_Loaded"
/>
The value is correctly updated when the user selects an item in the dropdown menu, but cause the combobox IsEditable the user is able to type whatever he wants that it's not a value in the ItemSource. In this case the SelectedValue does NOT change.
What I need to do is to enable a button when the SelectedValue is among those in the ItemsSource.
Do you have some hint?

Your wpf combobox has a property "Text" that contains the text input by the user. You will have to write some code to check if the entered text matches anything in your itemssource.

<Button Content="Click">
<Button.Style>
<Style TargetType="Button">
<Setter Property="IsEnabled" Value="True"/>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=ServiceTypeComboBox, Path=SelectedValue}" Value="{x:Null}">
<Setter Property="IsEnabled" Value="False"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>

Related

Enable or disable a TextBox depending on the selected ComboBoxItem

I have a Combobox and some text Boxes, I want to disable some text boxes deppending on the selected item in the ComboBox.
the Xaml code:
<ComboBox Name="Combo" ItemsSource="{Binding ModeReglementList}"}"/>
<TextBox IsEnabled="{Binding ElementName=Combo, .........}"/>
What is the simplest way to accomplish this dependency control in WPF?
You could apply a Style with data triggers to the TextBox.
In the below markup, the TextBox will be disabled when you select "b" in the ComboBox:
<ComboBox Name="Combo" ItemsSource="{Binding ModeReglementList}" />
<TextBox>
<TextBox.Style>
<Style TargetType="TextBox">
<Style.Triggers>
<DataTrigger Binding="{Binding SelectedItem, ElementName=Combo}" Value="b">
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
View Model:
public IEnumerable<string> ModeReglementList { get; } =
new string[] { "a", "b", "c" };
You can add other triggers to trigger on different values.

WPF combobox selected index

I have a combobox which I'm setting it's itemsSource after getting it from a database, for some reason the combobox doesn't show the first item.
My comboBox:
<ComboBox Text="Add To Message:" ItemsSource="{Binding Messages}" SelectedValue="{Binding SelectedMessage}" Style="{StaticResource comboStyle}"/>
My style:
<Style TargetType="ComboBox" x:Key="comboStyle">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=SelectedItemId}" Value="-1">
<Setter Property="SelectedIndex" Value="1"/>
</DataTrigger>
</Style.Triggers>
</Style>
Instead of setting SelectedIndex you should set SelectedMessage:
// get data from db...
SelectedMessage = Messages.FirstOrDefault();

WPF Default Value (using Style Trigger) with Binding

I'm new to WPF so please bear with me. I have a ComboBox on my WPF window, the ItemSource property is bound to a List of strings property (Countries) and the SelectedItem is bound to a string property (SelectedCountry). Both of these properties are in the code behind - and I'm setting the DataContext to "this" (i.e. the Window).
The ComboBox xaml is:
<ComboBox Name="CountryComboBox"
VerticalAlignment="Center"
Width="200"
ItemsSource="{Binding Path=Countries, Mode=OneTime}"
SelectedItem="{Binding Path=SelectedCountry, Mode=TwoWay}">
</ComboBox>
I wanted to have a default "- Please Select -" option that is displayed when an item is not selected, therefore I placed the following xaml in App.xaml:
<Style TargetType="ComboBox">
<Style.Triggers>
<Trigger Property="SelectedItem" Value="{x:Null}">
<Setter Property="IsEditable" Value="true" />
<Setter Property="IsReadOnly" Value="true" />
<Setter Property="Text" Value="- Please Select -" />
</Trigger>
</Style.Triggers>
</Style>
When my window is first displayed, the combobox does have the "- Please Select -" text as expected. When I then select a value in the combobox, the SelectedCountry gets populated appropriately, but then when I assign "null" to the SelectedCountry property the combobox still has the same selected country when I'd expect it to go back to "- Please Select -". What am I doing wrong?
Thanks.
It may be a better option not to modify the ComboBox and simply overlay a TextBlock over the ComboBox when the SelectedItem is null.
Just wrap the ComboBox and a TextBlock in a Grid and set a DataTrigger on the TextBlock to check if the SelectedItem is null and toggle its Visibility
Example:
<Grid>
<ComboBox x:Name="combo" ItemsSource="{Binding Countries}" SelectedItem="{Binding SelectedItem}" />
<TextBlock x:Name="textblock" Text="- Please Select -" Margin="5,3,0,0" IsHitTestVisible="False">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Visibility" Value="Hidden" />
<Style.Triggers>
<DataTrigger Binding="{Binding SelectedItem,ElementName=combo}" Value="{x:Null}">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</Grid>
Result:
You need to insert a record into the Countries list that has a value of null and the name " - Please Select - ".
Alternatively I suppose you could extend the ComboBox control and write your own so that you could specify the null vale in the list without having to put a record into the Countries selection.
But of the two, it is much easier to just add a record to Countries.

Is there a way to get the DataContext for a bound Property

Is there a way in code to get the the DataContent for the Text Property of the ComboBox defined below?
<ComboBox Height="21" Text="{Binding Path=Field1.Value}">
<ComboBox.Resources>
<Style TargetType="ComboBox">
<Setter Property="IsEnabled" Value="False" />
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Field2.Value}" Value="">
<Setter Property="IsEnabled" Value="True" />
</DataTrigger>
</Style.Triggers>
</Style>
</ComboBox.Resources>
</ComboBox>
Currently the DataContext of the ComboBox is the user control in which it lives. Which makes sense because I want my Text bound to one property and my DataTrigger to be bound to another property. But I need to get the DataContext that's being bound to for the Text property.
Something like this should do it:
Binding binding = BindingOperations.GetBinding(yourComboBox, ComboBox.TextProperty);
object theDataContext = binding.Source;

Wpf Combobox selectedvalue trigger

I am trying to change the visibility with a trigger when a particular value in a combobox is selected, and I got the following XAML
<ItemsControl ItemsSource="{Binding AccessControl.Credentials}" >
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid >
<ComboBox Name="chkFieldType"
SelectedValue="{Binding Path=ValueSourceType,Converter={StaticResource enumstringConv}}"
SelectedValuePath="Tag" SelectionChanged="chkFieldType_SelectionChanged" >
<ComboBoxItem Tag="User">User</ComboBoxItem>
<ComboBoxItem Tag="SessionCredential">Field</ComboBoxItem>
<ComboBoxItem Tag="Inherit">From other Resource</ComboBoxItem>
</ComboBox>
<Border " Visibility="Hidden">
<Border.Resources>
<Style TargetType="{x:Type Border}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=SelectedValue, ElementName=chkFieldType}" Value="Inherit">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Resources>
<ComboBox/>
</Border>
In this case a border. The selected value is "Inherit" of type string but the border remainds hidden.
I ran into the same problem and found that you have to set the visibility property using the style only. So instead of having the initial visibility set with:
<Border Visibility="Hidden">
You should set the initial visibility using the style:
<Style TargetType="....">
<Setter Property="Visibility" Value="Hidden"/>
<Style.Triggers>
....
</Style.Triggers>
</Style>
(I know it's kinda overdue but I thought maybe someone else might run into the same problem).
Try SelectedItem.Tag or SelectedItem.Content instead of SelectedValue
Set your binding on SelectedValue, not SelectedItem.SelectedValue. The way you currently have it, it is looking for ComboBoxItem.SelectedValue, which doesn't exist
<DataTrigger Value="Inherit"
Binding="{Binding Path=SelectedValue,
Converter={StaticResource enumstringConv},
ElementName=chkFieldType}">
I think it's because you are putting the DataTrigger in Border.Resources.
Try putting the style in the window.resources, with a x:key in order to apply the style to the border.
I think that the border.resources can not access to a control "outside it's own resources context"
SelectedItem and SelectedValue are two seperate properties on the ComboBox.
Since your ComboBoxItems are all strings you can change
<DataTrigger Binding="{Binding Path=SelectedItem.SelectedValue, ElementName=chkFieldType}" Value="Inherit">
to
<DataTrigger Binding="{Binding Path=SelectedItem, ElementName=chkFieldType}" Value="Inherit">
I ended up setting the visibility manually via the code behind when the selectedItem event is fired..

Resources