C # WPF Combobox editable only allows list option

I have a combobox with names in it. I have an editing kit installed so that the user can enter a name. I want the user to only be able to enter a name that is already in the list. When the user clicks the Save button, I want the window to display a red check box if the field is empty or not in the list. Is there any way to do this?

<ComboBox IsEditable="True" Grid.Column="2" Grid.Row="1" Margin="5,3,0,0" Text="{Binding Model.Number}" ItemsSource="{Binding DList}" SelectedItem="{Binding Model.Number}" IsEnabled="{Binding EnableComboBox}" VerticalAlignment="Top"> </ComboBox> 
+5
source share
2 answers

If I understand correctly, you want the user to be able to select an existing list item by entering it, but do not enter a line that is not in the list. This can be done as follows:

 <ComboBox IsEditable="False"></ComboBox> 

This will allow the user to start typing a string, but you are losing the text box for input.

Another way to do this is to let the user enter whatever they want by setting <ComboBox IsReadOnly="False" IsEditable="True"> and handle, for example, the LostFocus event to check if the input is valid. Here is an example:

 private void ComboBox_LostFocus(object sender, RoutedEventArgs e) { bool allowed = false; foreach (ComboBoxItem it in comboBox.Items) { if (it.Content.ToString() == comboBox.Text) { allowed = true; break; } } if (!allowed) { MessageBox.Show("MISS!"); } else { MessageBox.Show("HIT!"); } } 

For some reason, I was not able to set the border color quickly, but you got the point from here. In addition, depending on the type of ComboBoxItem you may need to map comboBox.Text to a specific property.

+1
source

Suppose you are using MVVM (this is not what you are doing now), and that

 ItemsSource="{Binding DList}" 

is the correct binding to a set of models

You will need

 DisplayMemberPath="Number" 

Let's get back to your question. First write another anchor for the selected text

 Text="{Binding Selected, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors =true, NotifyOnValidationError=true}" 

and embed a validation tooltip inside the combo

 ToolTip="{Binding ElementName=customAdorner, Path=AdornedElement.(Validation.Errors)[0].ErrorContent}" 

and style in window resources

 <Window.Resources> <Style TargetType="{x:Type Label}"> <Setter Property="Margin" Value="5,0,5,0" /> <Setter Property="HorizontalAlignment" Value="Right" /> </Style> <Style TargetType="{x:Type ComboBox}"> <Setter Property="VerticalAlignment" Value="Center" /> <Setter Property="Margin" Value="0,2,40,2" /> <Setter Property="Validation.ErrorTemplate"> <Setter.Value> <ControlTemplate> <DockPanel LastChildFill="true"> <Border Background="Red" DockPanel.Dock="right" Margin="5,0,0,0" Width="20" Height="20" CornerRadius="10" ToolTip="{Binding ElementName=customAdorner, Path=AdornedElement.(Validation.Errors)[0].ErrorContent}"> <TextBlock Text="!" VerticalAlignment="center" HorizontalAlignment="center" FontWeight="Bold" Foreground="white"> </TextBlock> </Border> <AdornedElementPlaceholder Name="customAdorner" VerticalAlignment="Center" > <Border BorderBrush="red" BorderThickness="1" /> </AdornedElementPlaceholder> </DockPanel> </ControlTemplate> </Setter.Value> </Setter> </Style> </Window.Resources> 

Finally, we must check the ViewModel property

We can project a list of models on our numbers to check for errors.

  public class VM : IDataErrorInfo { public string this[string columnName] { get { if (columnName.Equals( "Selected")) { if (!DList.Select(m => m.Number).Contains(Selected)) return "Selected number must be in the combo list"; } return null; } } 

You can learn more about data validation in MVVM, for example here

Redeem verification later

Suppose you want to test after clicking save

  <Button Content="Save" Command="{Binding SaveCmd}" 

you just need to raise the property changed in the corresponding delegate command

  public class VM : ViewModelBase, IDataErrorInfo { private bool showValidation; private int selected; public int Selected { get { return selected; } set { selected = value; showValidation = true; OnPropertyChanged("Selected"); } } DelegateCommand saveCmd; public ICommand SaveCmd { get { if (saveCmd == null) { saveCmd = new DelegateCommand(_ => RunSaveCmd(), _ => CanSaveCmd()); } return saveCmd; } } private bool CanSaveCmd() { return true; } private void RunSaveCmd() { showValidation = true; OnPropertyChanged("Selected"); } 

and exit the check before you want to show it.

  public string this[string columnName] { get { if (!showValidation) { return null; } 
+1
source

Source: https://habr.com/ru/post/1264082/


All Articles