Как изменить редактируемый текст ComboBox на что-то другое, если выбран конкретный ComboBoxItem? - PullRequest
0 голосов
/ 07 мая 2019

Новый текст никогда не будет присутствовать в элементах внутри ComboBox. Ниже приведен полный код XAML +, который работает не так, как я хочу. Я пытаюсь добиться того, чтобы пользователь выбрал фактическую группу элементов из поля со списком или элемент No Group (курсив, выделен серым цветом), который должен применяться в качестве пустой строки в текстовое поле внутри ComboBox.

Я тоже пробовал:

  1. с StaysOpenOnEdit="True" (с тем же результатом) и
  2. путем обработки события Selected "click me" ComboBoxItem (обработчик события вызывается до изменения свойств Text или SelectedItem ComboBox).

1022 * XAML * <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;
}

Ожидается: когда пользователь нажимает на элемент "щелкни меня" в раскрывающемся списке, текст ComboBox становится пустой строкой. Остальные элементы при нажатии должны копировать свой текст в обычном текстовом поле ComboBox.

.

Фактический:

  1. Запустите программу.
  2. Выберите пункт "нажмите меня".
  3. Текст изменится на «щелкни по мне» (не будет выделен серым цветом) вместо «».
  4. Нажмите на пункт «Тест».
  5. Текст меняется на "" (пустая строка) вместо "test".
  6. Снова нажмите на пункт «Тест».
  7. Текст меняется на «тест».

Обновление

Я хочу использовать MVVM, но я все еще начинающий. У меня есть несколько ComboBox, как показано выше внутри DataGridTemplateColumn, и для каждого из ComboBox (которое должно иметь одинаковое раскрывающееся содержимое), я думаю, что у меня должен быть ViewModel для каждого из ComboBoxItem s. Если возможно, я бы хотел узнать, как правильно использовать MVVM в этой ситуации.

Большой XAML

<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;
}

1 Ответ

1 голос
/ 07 мая 2019

ComboBox.Text не будет обновляться немедленно в событии SelectionChanged. Вместо этого вы можете использовать содержимое SelectedValue. И установите SelectedValue на ноль. Измените условие if следующим образом.

if ((cb.SelectedValue as ComboBoxItem).Content.ToString() == "click me")
{
    cb.Text = "";
    cb.SelectedValue = null;
    e.Handled = true;
}
...