【发布时间】:2017-11-16 07:27:05
【问题描述】:
在我之前的问题How to change ComboBox item visibility 之后,由于问题略有改变,我决定开一个新帖子来解决它。对于那些不想阅读上一篇文章中所有 cmets 的人,这里是情况。
我有一个在运行时生成的 DataGrid。此数据网格的每一列在标题内都有一个组合框。所有这些组合框都具有相同的 Source,即类项的可观察集合。每个项目都显示一个我在组合框的 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 个 Item (x,y,a,b) 的集合。如果在 ComboBox1 中选择了 x,则在 ComboBox1 的 SelectedItem 更改(例如从 x 到 y)之前,无法在 2 个 ComboBox 中选择 x。现在我什至可以接受这样一个事实,即下拉菜单中的项目只是被禁用,如果它使事情变得更容易,我只需要这样一个事实,即如果他已经被选中,它就不能再次被选中。
问题在于,此解决方案适用于每个具有 ItemContainerGenerator.Status = NotStarted 的 ComboBox(这意味着 ComboBoxItem 仍未创建)。如果我打开一个组合框的下拉列表,那么无论我做什么,它的 ComboBox 项都将保留它们的样式(因为 ItemContainerGenerator.Status = ContainersGenerated),而我没有打开的组合框会跟踪可见性的变化项目。
我正在寻找重新创建这些项目的解决方案,以便应用具有可见性更改的新样式
【问题讨论】:
-
让我们忘记
DataGrid和所有其他问题的噪音......我建议您创建一个MCVE,其中包含3 个组合框和组合框项目源中的4 个项目。我有一些解决问题的想法,但我没有时间自己创建 MCVE,我需要一个来测试我的解决方案;) -
我找到了解决方案。我发布了它,但如果我能找到更好的方法来做到这一点,我会很好。不幸的是,我现在在工作,没有时间创建 MCVE
-
Selezionato是否与INotifyPropertyChanged正确实现?如果没有,您可以先更改此方面,而不是创建 MCVE。我不着急,所以除非你很着急,否则请慢慢来 MCVE ;) -
@grek40 我刚刚发现我实现了事件,但没有实现 INotifyPropertyChanged 类。我觉得自己很笨
-
嗯,这是有道理的......如果值实际上没有改变,你的
c.Items.Refresh()将不起作用,因为它起作用了,唯一缺少的是自动更新的更改通知,而不是显式刷新。
标签: wpf combobox itemcontainerstyle itemcontainergenerator