Reputation: 3461
The new text will never be present in the items inside ComboBox
. Below is the full XAML + code-behind that does not work as I wish. What I am trying to achieve is to have the user select an actual group of items from the combo box, or a No Group
(italic, grayed out) item that should be applied as an empty string in the text box inside the ComboBox
.
I also tried:
StaysOpenOnEdit="True"
(with the same result) andSelected
event of the "click me"
ComboBoxItem
(the event handler is called before the Text
or SelectedItem
properties of the ComboBox change).<Window x:Class="cs_wpf_test_12.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:cs_wpf_test_12"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<StackPanel Orientation="Vertical">
<ComboBox SelectionChanged="ComboBox_SelectionChanged"
IsEditable="True">
<ComboBoxItem>test</ComboBoxItem>
<ComboBoxItem Foreground="Gray">click me</ComboBoxItem>
</ComboBox>
</StackPanel>
</Window>
internal bool HandlingSelectionChange = false;
private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (HandlingSelectionChange)
{
return;
}
HandlingSelectionChange = true;
var cb = sender as ComboBox;
if (cb.Text == "click me")
{
cb.Text = "";
e.Handled = true;
}
HandlingSelectionChange = false;
}
Expected: when the user clicks on the "click me" item in the drop-down the text of the ComboBox
becomes an empty string. The rest of the items, when clicked, should copy their text normally into the text box of the ComboBox
.
Actual:
I wish to use MVVM but I am still a beginner. I have several ComboBox
es like shown above inside a DataGridTemplateColumn
, and for each of the ComboBox
es (which should have the same drop-down contents) I think I should have a ViewModel for each of its ComboBoxItem
s. If possible, I would like to learn how I could I use MVVM correctly in this situation.
<DataGridTemplateColumn Header="Group Name">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Label Content="{Binding GroupName, Mode=OneWay}">
</Label>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox IsEditable="True" StaysOpenOnEdit="True"
ItemsSource="{Binding Path=Clocks.GroupsVM,
RelativeSource={RelativeSource AncestorType=local:ClockDataGrid}}"
PreviewKeyDown="ComboBox_PreviewKeyDown"
SelectionChanged="ComboBox_SelectionChanged"
Text="{Binding GroupName}">
<ComboBox.Resources>
<Style TargetType="ComboBoxItem">
<Setter Property="FontStyle" Value="{Binding FontStyle}"/>
<Setter Property="Foreground" Value="{Binding Foreground}"/>
</Style>
</ComboBox.Resources>
</ComboBox>
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>
private void ComboBox_PreviewKeyDown(object sender, KeyEventArgs e)
{
var cb = sender as ComboBox;
if ((e.Key == Key.Return ||
e.Key == Key.Enter) &&
cb.Text != "")
{
bool duplicate = false;
foreach (ClockGroupVM vm in Clocks.GroupsVM)
{
if (vm.Name == cb.Text)
{
cb.SelectedItem = vm;
duplicate = true;
break;
}
}
if (duplicate)
{
return;
}
// create a ClockGroupM and corresponding ClockGroupVM
// (ClockGroupVM inherits from ClockGroupM)
var cvm = new ClockGroupVM()
{
Name = cb.Text
};
Clocks.Groups.Insert(0, cvm);
cb.SelectedItem = cvm;
}
}
internal bool HandlingSelectionChange = false;
private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (HandlingSelectionChange)
{
return;
}
HandlingSelectionChange = true;
var cb = sender as ComboBox;
//if (cb.SelectedItem is the VM with Style != Normal)
ClockGroupVM foundVM = null;
foreach (ClockGroupVM vm in Clocks.GroupsVM)
{
if (vm.FontStyle != FontStyles.Normal &&
ReferenceEquals(cb.SelectedItem, vm))
{
foundVM = vm;
break;
}
}
if (foundVM != null)
{
cb.Text = "";
e.Handled = true;
}
HandlingSelectionChange = false;
}
Upvotes: 0
Views: 1490
Reputation: 2044
ComboBox.Text wont update immediately in the SelectionChanged event. You can use SelectedValue's content instead. And set SelectedValue to null. Change your if condition like this.
if ((cb.SelectedValue as ComboBoxItem).Content.ToString() == "click me")
{
cb.Text = "";
cb.SelectedValue = null;
e.Handled = true;
}
Upvotes: 1