Bonjour,

J'ai un objet métier qui implémente INotifyPropertyChanged.
Cet objet a une propriété IsSelected qui prévient correctement sa modification.

Je donne comme source à un datagrid une ICollectionView remplit de mon objet métier.

Je redéfinis le style de DataGridRow pour bind la propriété IsSelected de l'objet métier à celle du DataGridRow, ainsi sur selection des lignes de ma datagrid, mes objets en son informé.

J'ai un bouton sur lequel je veux bind la propriété IsEnabled sur ma collection à l'aide d'un convertisseur qui retourne True ou False si une propriété IsSelected d'un des objets métiers de la collection est à True.

Tout fonctionne bien, sauf que quand je selectionne une ligne, la propriété IsSelected de l'objet associé est bien miste à True, mais le binding sur IsEnabled de mon bouton n'est pas réévalué.

Comment faire en sorte que la collection notify ce changement ?

Objet métier implémentant INotifyPropertyChanged

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 
private bool isSelected;
        [Browsable(false)]
        public bool IsSelected
        {
            get
            {
                return isSelected;
            }
            set
            {
                isSelected = value;
                OnPropertyChanged("IsSelected");
            }
        }
DataGrid

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
 
<my1:Tableau ItemsSource="{Binding ItemsSource, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type parametrage:ParametrageSimple}}, Mode=OneWay}" 
                              SelectedItem="{Binding SelectedItem, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type parametrage:ParametrageSimple}}, Mode=TwoWay}"
                              AutoGenerateColumns="True" HorizontalAlignment="Stretch" x:Name="extendedDataGrid1" VerticalAlignment="Stretch" Margin="0,0,33,30" MinHeight="180"
                              SelectionMode="Extended" CanUserSortColumns="False" IsReadOnly="True" ColumnWidth="*" >
            <my1:Tableau.ItemContainerStyle>
                <Style>
                    <Setter Property="DataGridRow.IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
                </Style>
            </my1:Tableau.ItemContainerStyle>
        </my1:Tableau>
Bouton

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
 
<boutons:BoutonIconeSupprimer IsEnabled="{Binding ItemsSource,  Converter={converters:CollectionHaveSelectedToBoolConverter}, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type src:UCParametrageTableau}}, Mode=OneWay}"
            Name="btnIconeSupprimer" VerticalAlignment="Center" Grid.Row="2" Margin="0,5" />
Chargement de la collection

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
 
 
 public static DependencyProperty ItemsSourceProperty =
             DependencyProperty.Register("ItemsSource", typeof(ICollectionView), typeof(ParametrageSimple), new PropertyMetadata(null));
 
        public ICollectionView ItemsSource
        {
            get { return (ICollectionView)(GetValue(ItemsSourceProperty)); }
            set { SetValue(ItemsSourceProperty, value); }
        }
 
        public static DependencyProperty SelectedItemProperty =
             DependencyProperty.Register("SelectedItem", typeof(Object), typeof(ParametrageSimple), new PropertyMetadata(null));
 
        public Object SelectedItem
        {
            get { return (GetValue(SelectedItemProperty)); }
            set { SetValue(SelectedItemProperty, value); }
        }
...
 
ItemsSource = CollectionViewSource.GetDefaultView(new List<BrancheVM>());
foreach (var item in serviceBranche.GetAll(AccesApplication.AccesApplication, null))
                            (ItemsSource as ListCollectionView).AddNewItem(new BrancheVM(item));
                        (ItemsSource as ListCollectionView).CommitNew();
Convertisseur

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
 
class CollectionHaveSelectedToBoolConverter : MarkupExtension, IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if ((value as ICollectionView) != null)
            {
                return LookForSelected(value as ICollectionView);
            }
 
            return false;
        }
 
        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return null;
        }
 
        public bool LookForSelected(ICollectionView source)
        {
            bool haveSelected = false;
            if (source != null)
                foreach (var item in source)
                {
                    if (haveSelected)
                        break;
                    if ((item as IHierarchical) != null)
                        if (haveSelected = LookForSelected((item as IHierarchical).Childs))
                            break;
                    if ((item as ISelected) != null)
                        haveSelected = (item as ISelected).IsSelected;
                }
            return haveSelected;
        }
 
        private static CollectionHaveSelectedToBoolConverter converter = null;
        public override object ProvideValue(IServiceProvider serviceProvider)
        {
            if (converter == null) converter = new CollectionHaveSelectedToBoolConverter();
            return converter;
        }
    }
Merci pour votre aide.

PS : Je peux évidement passer par une ICommand, ce qui fonctionne très bien, cependant, je n'ai pas l'air de maitriser quand est ce que la commande re-évalue la méthode canExecute, ce qui me gène un peu quand il s'agit d'évaluer une collection entière.