I know that this topic is already answered, but i couldn't solve the problem with the solution that i found. So here is my code:
<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 SelectedValue="{Binding Selezione}" SelectedValuePath="Selezionato" Width="100" Height="20" ItemsSource="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}},Path=DataContext.Selezione}" SelectionChanged="Test_SelectionChanged">
<ComboBox.ItemTemplate>
<DataTemplate >
<TextBlock Text="{Binding Path=Oggetto}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</DataGrid.ColumnHeaderStyle>
</DataGrid>
In few words, i have a custom datagrid which is bound to a datatable. The header of each column, is a combobox, whose source is an observable collection of this class:
public class PopolazioneCombo
{
public string Oggetto { get; set; }
private bool selezionato = false;
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propName)
{
var handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propName));
}
}
public bool Selezionato
{
get { return !selezionato; }
set
{
if(selezionato != value)
{
selezionato = value;
OnPropertyChanged("Selezionato");
}
}
}
}
My problem is the following: I need to switch the visibility of each selected item to collapsed in all the comboboxes (since they share the same source). I tried to create a custom SelectionChanged event in which i change the "Selezionato" value and i bound the visibility of the textblock like this:
<TextBlock Text="{Binding Path=Oggetto}" Visibility="{Binding Path=Selezionato, Converter={StaticResource BoolToVis}, UpdateSourceTrigger=PropertyChanged}"/>
The problem with this is that, not only it make my SelectedItem not visible in the combobox, but also the ComoBoxItem are not synchronized, so it's not working at all as intended.
EDIT: this is the collection
public ObservableCollection<PopolazioneCombo> Selezione
{
get
{
return selezione;
}
set
{
if (selezione != value)
{
selezione = value;
OnPropertyChanged("Selezione");
}
}
}
EDIT 2: My requirement is that, if in any of the N combobox an item is selected, then, that item cannot be selected by anyone, until he lose the SelectedItem status. For instance let's assume i have 2 combobox and a collection of 4 Item (x,y,a,b) . If x is selected in ComboBox1, then x can't be selected in none of the 2 ComboBox until the SelectedItem of the ComboBox1 change (from x to y for instance). Now i can even accept the fact that the item in the dropdown is just disabled if it makes the things easier, i just need the fact that it cannot be selected again if he is already selected
The requirements:
We'll do the hiding and disabling with triggers in an ItemContainerStyle
on the comboboxes, driven by the bool Selezionato
property of the combo box items. We'd prefer to set Selezionato
with a Binding
in the style as well, but I found that it was deselecting items at times when I didn't want it to, so I did it in a ComboBox.SelectionChanged
handler instead.
<Style
x:Key="SingleSelectionComboBoxItem"
TargetType="ComboBoxItem"
BasedOn="{StaticResource {x:Type ComboBoxItem}}"
>
<!-- This unselects sometimes when you don't want it to. -->
<!--
<Setter Property="IsSelected" Value="{Binding Selezionato, Mode=OneWayToSource}" />
-->
<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>
ComboBoxes. I'm leaving out some of the properties you had. What matters for my addition to your code is ItemContainerStyle
and SelectionChanged
:
<ComboBox
ItemsSource="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}, Path=DataContext.Selezione}"
DisplayMemberPath="Oggetto"
ItemContainerStyle="{StaticResource SingleSelectionComboBoxItem}"
SelectionChanged="SingleSelectionComboBox_SelectionChanged"
/>
Code behind:
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;
}
}
Another thing I noticed along the way:
You had the PopolazioneCombo.Selezionato
getter returning !selezionato
-- probably a typo, but if not, a bad idea!
public bool Selezionato
{
get { return selezionato; }
set
{
if (selezionato != value)
{
selezionato = value;
OnPropertyChanged("Selezionato");
}
}
}