WPF:如何重新创建ItemContainer?

WPF:如何重新创建ItemContainer?,wpf,combobox,itemcontainerstyle,itemcontainergenerator,Wpf,Combobox,Itemcontainerstyle,Itemcontainergenerator,根据我的上一个问题,由于问题略有改变,我决定打开一个新的帖子来解决这个问题。对于那些不想阅读上一篇文章中所有评论的人来说,情况是这样的 我有一个在运行时生成的DataGrid。此datagrid的每一列在标题中都有一个组合框。所有这些组合框都有相同的源,即类项的可观察集合。每个项目都显示一个属性,我在ComboBox的ItemContainerStyle中使用该属性来决定每个ComBoBoxItem是否应该可见 现在,据我所知,WPF是这样工作的:如果视图包含combobox或treeview之

根据我的上一个问题,由于问题略有改变,我决定打开一个新的帖子来解决这个问题。对于那些不想阅读上一篇文章中所有评论的人来说,情况是这样的

我有一个在运行时生成的DataGrid。此datagrid的每一列在标题中都有一个组合框。所有这些组合框都有相同的源,即类项的可观察集合。每个项目都显示一个属性,我在ComboBox的ItemContainerStyle中使用该属性来决定每个ComBoBoxItem是否应该可见

现在,据我所知,WPF是这样工作的:如果视图包含combobox或treeview之类的控件,那么它们的项(即ComboBoxItem、TreeViewItem…)将在不需要时生成(例如当打开combobox下拉列表时)。如果我应用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>

选择已更改:

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;
        }
    }
private void SingleSelectionComboBox\u SelectionChanged(对象发送者,SelectionChangedEventArgs e)
{
foreach(e.RemovedItems.OfType()中的变量项)
{
item.Selezionato=false;
}
foreach(e.AddedItems.OfType()中的变量项)
{
item.Selezionato=true;
}
}
我的要求是,如果在任意N组合框中选择了一个项目,则任何人都不能选择该项目,直到他失去SelectedItem状态。例如,假设我有2个组合框和4个项目(x,y,a,b)的集合。如果在ComboBox1中选择了x,则在Combox1的SelectedItem更改(例如从x更改为y)之前,无法在2个Combox1中的任何一个中选择x。现在,我甚至可以接受这样一个事实,即下拉列表中的项目只是被禁用,如果它使事情变得更容易,我只需要一个事实,即如果他已经被选中,它就不能再次被选中

问题在于,此解决方案适用于具有ItemContainerGenerator.Status=NotStarted的每个ComboBox(这意味着ComboBoxItem仍然没有创建)。如果我打开一个组合框的下拉列表,那么无论我做什么,它的组合框项目都将保持它们的样式(因为ItemContainerGenerator.Status=ContainerGenerated),而我没有打开的组合框会跟踪项目可见性的变化


我正在寻找一个解决方案来重新创建这些项目,以便在可视性发生变化的情况下应用新样式

在互联网上进行了一次幸运的研究(即,我找到了正确的关键字组合),我发现了这个奇妙的方法,因此更新后的解决方案如下:

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,那就更好了。

在互联网上进行了一次幸运的研究(即,我找到了关键字的正确组合),我发现了这个奇妙的方法,因此更新的解决方案如下:

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,那就更好了

让我们忘掉
数据网格
和所有其他问题。。。我建议您创建一个包含3个组合框和组合框itemssource中的4个项目的列表。我有一些解决问题的想法,但我没有时间自己创建MCVE,我需要一个来测试我的解决方案;)我找到了解决办法。我把它贴了出来,但如果我能找到更好的方法,我会很高兴的。不幸的是,现在我正在工作,我没有时间创建一个MCVEIs
Selezionato
,它是用
INotifyPropertyChanged
正确实现的?如果没有,您可以首先更改此方面,而不是创建MCVE。我不赶时间,所以除非你赶时间,否则就慢慢来看看MCVE;)@grek40我刚刚发现我实现了事件,但没有实现类INotifyPropertyChanged。我觉得很傻,这是有道理的。。。如果该值没有实际更改,您的
c.Items.Refresh()
将无法工作,因为它可以工作,唯一缺少的是自动更新而不是显式刷新的更改通知。让我们忘记
DataGrid
和所有其他问题的噪音。。。我建议您创建一个包含3个组合框和组合框itemssource中的4个项目的列表。我有一些解决问题的想法,但我没有时间自己创建MCVE,我需要一个来测试我的解决方案;)我找到了解决办法。我把它贴了出来,但如果我能找到更好的方法,我会很高兴的。不幸的是,现在我正在工作,我没有时间创建一个MCVEIs
Selezionato
,它是用
INotifyPropertyChanged
正确实现的?如果没有,您可以首先更改此方面,而不是创建MCVE。我不赶时间,所以除非你赶时间,否则就慢慢来看看MCVE;)@grek40我刚刚发现我实现了事件,但没有实现类INotifyPropertyChanged。我觉得很傻,这是有道理的。。。如果该值没有实际更改,您的
c.Items.Refresh()
将无法工作,因为它可以工作,唯一缺少的是自动更新而不是显式刷新的更改通知。