WPF:如何重新创建 ItemContainer?
WPF: how to recreate ItemContainer?
根据我之前的问题 ,由于问题略有变化,我决定打开一个新的 post 来解决它。对于那些不想看之前所有评论的人post,情况是这样的。
我有一个在 运行 时间生成的 DataGrid。此数据网格的每一列在 header 内都有一个组合框。所有这些组合框都具有相同的源,即 class 项的可观察 collection。每个项目都显示一个 属性,我在组合框的 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>
物品容器样式:
<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;
}
}
我的要求是,如果在N个combobox中的任何一个item被选中,那么那个item不能被任何人选中,直到他失去SelectedItem状态。例如,假设我有 2 个组合框和一个 collection 的 4 个 Item (x,y,a,b) 。如果在 ComboBox1 中选择了 x,则在 ComboBox1 的 SelectedItem 更改(例如从 x 更改为 y)之前,无法在 2 ComboBox 的 none 中选择 x。现在我什至可以接受这样一个事实,即下拉列表中的项目只是被禁用,如果它使事情变得更容易的话,我只需要这样一个事实,即如果他已经被选中,它就不能再次被选中。
问题在于此解决方案适用于每个具有 ItemContainerGenerator.Status = NotStarted 的 ComboBox(这意味着 ComboBoxItem 仍未创建)。如果我打开组合框的下拉列表,那么无论我做什么,它的组合框项目都将保留它们的样式(原因 ItemContainerGenerator.Status = ContainersGenerated),而我没有打开的组合框会跟踪可见性的变化的项目。
我正在寻找重新创建这些项目的解决方案,以便应用具有可见性更改的新样式
在互联网上幸运地研究之后(即我找到了正确的关键字组合),我发现了这个绝妙的方法,所以这里更新了解决方案:
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"/>
组合框神奇地显示了正确的更改。现在我不太喜欢隐藏代码,所以如果有办法在我的 Collection 中添加 属性,或者通过 xaml 会更好 [=12] =]
根据我之前的问题
我有一个在 运行 时间生成的 DataGrid。此数据网格的每一列在 header 内都有一个组合框。所有这些组合框都具有相同的源,即 class 项的可观察 collection。每个项目都显示一个 属性,我在组合框的 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>
物品容器样式:
<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;
}
}
我的要求是,如果在N个combobox中的任何一个item被选中,那么那个item不能被任何人选中,直到他失去SelectedItem状态。例如,假设我有 2 个组合框和一个 collection 的 4 个 Item (x,y,a,b) 。如果在 ComboBox1 中选择了 x,则在 ComboBox1 的 SelectedItem 更改(例如从 x 更改为 y)之前,无法在 2 ComboBox 的 none 中选择 x。现在我什至可以接受这样一个事实,即下拉列表中的项目只是被禁用,如果它使事情变得更容易的话,我只需要这样一个事实,即如果他已经被选中,它就不能再次被选中。
问题在于此解决方案适用于每个具有 ItemContainerGenerator.Status = NotStarted 的 ComboBox(这意味着 ComboBoxItem 仍未创建)。如果我打开组合框的下拉列表,那么无论我做什么,它的组合框项目都将保留它们的样式(原因 ItemContainerGenerator.Status = ContainersGenerated),而我没有打开的组合框会跟踪可见性的变化的项目。
我正在寻找重新创建这些项目的解决方案,以便应用具有可见性更改的新样式
在互联网上幸运地研究之后(即我找到了正确的关键字组合),我发现了这个绝妙的方法,所以这里更新了解决方案:
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"/>
组合框神奇地显示了正确的更改。现在我不太喜欢隐藏代码,所以如果有办法在我的 Collection 中添加 属性,或者通过 xaml 会更好 [=12] =]