WPF: как воссоздать ItemContainer?

После моего предыдущего вопроса Как изменить видимость элемента ComboBox, поскольку проблема немного изменилась, я решил открыть новое сообщение, чтобы решить ее. Для тех, кто не хочет читать все комментарии к предыдущему посту, вот ситуация.

У меня есть DataGrid, который создается во время выполнения. Каждый столбец этой таблицы данных имеет комбинированный список внутри заголовка. Все эти выпадающие списки имеют один и тот же источник, который является наблюдаемой коллекцией элемента класса. Каждый элемент показывает свойство, которое я использую в ItemContainerStyle в выпадающих списках, чтобы решить, должен ли каждый ComBoBoxItem быть видимым или нет.

Теперь, насколько мне известно, WPF работает следующим образом: если представление содержит элементы управления, такие как выпадающий список или древовидное представление, то их элементы (например, ComboBoxItem, TreeViewItem...) не будут генерироваться, пока в этом нет необходимости (например, когда раскрывающийся список с раскрывающимся списком). Если я применяю ItemContainerStyle, это сообщит цели, как должны быть созданы ее элементы. Проблема в том, что в момент создания этих элементов каждое изменение, которое мне нужно применить к стилю, не будет сохранено.

Вот мой код:

    <DataGrid HeadersVisibility="Column" Name="griglia" Grid.Row="2" ItemsSource="{Binding Path=Test}" AutoGenerateColumns="True" IsReadOnly="True" ScrollViewer.CanContentScroll="True" ScrollViewer.VerticalScrollBarVisibility="Visible" ScrollViewer.HorizontalScrollBarVisibility="Visible">
        <DataGrid.ColumnHeaderStyle>
            <Style TargetType="{x:Type DataGridColumnHeader}">
                <Setter Property="ContentTemplate" >
                    <Setter.Value>
                        <DataTemplate DataType="DataGridColumnHeader"  >
                            <ComboBox ItemContainerStyle="{StaticResource SingleSelectionComboBoxItem}" DisplayMemberPath="Oggetto" Width="100" Height="20" ItemsSource="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}},Path=DataContext.Selezione, UpdateSourceTrigger=LostFocus}"  SelectionChanged="SingleSelectionComboBox_SelectionChanged">
                            </ComboBox>
                        </DataTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </DataGrid.ColumnHeaderStyle>
    </DataGrid>

ItemContainerStyle:

     <Style x:Key="SingleSelectionComboBoxItem" TargetType="ComboBoxItem" BasedOn="{StaticResource {x:Type ComboBoxItem}}">
        <Style.Triggers>
            <DataTrigger Binding="{Binding Selezionato}" Value="True">
                <!-- Hide it -->
                <Setter Property="Visibility" Value="Collapsed" />
                <!-- Also prevent user from selecting it via arrows or mousewheel -->
                <Setter Property="IsEnabled" Value="False" />
            </DataTrigger>
        </Style.Triggers>
    </Style>

SelectionChanged:

private void SingleSelectionComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        foreach (var item in e.RemovedItems.OfType<PopolazioneCombo>())
        {
            item.Selezionato = false;
        }

        foreach (var item in e.AddedItems.OfType<PopolazioneCombo>())
        {
            item.Selezionato = true;
        }
    }

Мое требование состоит в том, что, если в любом из выпадающего списка N выбран элемент, то этот элемент не может быть выбран никем, пока он не потеряет статус SelectedItem. Например, давайте предположим, что у меня есть 2 комбинированных списка и коллекция из 4 элементов (x,y,a,b) . Если x выбран в ComboBox1, то x не может быть выбран ни в одном из 2 ComboBox, пока SelectedItem ComboBox1 не изменится (например, с x на y). Теперь я могу даже принять тот факт, что элемент в раскрывающемся списке просто отключен, если он делает вещи проще, мне просто нужен факт, что его нельзя выбрать снова, если он уже выбран.

Проблема заключается в том, что это решение работает для каждого ComboBox, у которого есть ItemContainerGenerator.Status = NotStarted (это означает, что ComboBoxItem все еще не создан). Если я открою раскрывающийся список со списком, то элементы ComboBox сохранят свой стиль независимо от того, что я делаю (потому что ItemContainerGenerator.Status = ContainersGenerated), в то время как не раскрытый ящик со списком отслеживают изменения в видимости Предметы.

Я ищу решение для воссоздания этих элементов, которое будет применять новый стиль с изменениями в видимости

1 ответ

Решение

После удачного исследования в Интернете (то есть я нашел правильную комбинацию ключевых слов), я нашел этот замечательный метод, поэтому вот обновленное решение:

private void ComboBox_DropDownOpened(object sender, EventArgs e)
    {
        ComboBox c = sender as ComboBox;
        c.Items.Refresh();
    }

добавьте это событие в xaml, чтобы оно стало:

<ComboBox DropDownOpened="ComboBox_DropDownOpened" ItemContainerStyle="{StaticResource SingleSelectionComboBoxItem}" DisplayMemberPath="Oggetto" Width="100" Height="20" ItemsSource="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}},Path=DataContext.Selezione, UpdateSourceTrigger=LostFocus}"  SelectionChanged="SingleSelectionComboBox_SelectionChanged"/>

и волшебным образом выпадающий список показывает правильные изменения. Теперь я не большой поклонник кода, поэтому, если есть способ сделать это, добавив свойство в мою коллекцию, или через xaml, было бы лучше

Другие вопросы по тегам