2016-11-30 2 views
0

Résumé de la question: Y at-il un moyen en XAML de s'assurer que mon composant DataGrid est entièrement chargé avant d'initier une liaison sur la propriété SelectedIndex?Datagrid La liaison SelectedIndex ne fonctionnera pas dans XAML


Mon ViewModel est configuré comme ceci. J'utilise MVVM-light pour notifier la vue des changements. Je passe le nouveau modèle à SetData() chaque fois qu'il est mis à jour à partir du serveur.

public class MyViewModel : ViewModelBase 
{ 
    public void SetData(DataModel model) 
    {     
     Data = model.Data; //Array of 75 DataObjects 
     DataIndex = model.Index; //int between 0 and 74 
    } 

    // Array to Bind to Datagrid ItemsSource 
    public DataObject[] Data 
    { 
     get { return _data; } 
     private set 
     { 
      if (_data!= value) 
      { 
       _data= value; 
       RaisePropertyChanged("Data"); 
      } 
     } 
    } 
    private DataObject[] _data; 

    // Int to Bind to Datagrid SelectedIndex 
    public int DataIndex 
    { 
     get { return _index; } 
     private set 
     { 
      if (_index != value) 
      { 
       _index = value; 
       RaisePropertyChanged("DataIndex"); 
      } 
     } 
    } 
    private int _index; 
} 

La vue ressemble à ceci:

<Application.Resources> 
    <ResourceDictionary> 
     <core:ViewModelLocator x:Key="Locator" /> 
    </ResourceDictionary> 
</Application.Resources> 

<DataGrid ItemsSource="{Binding MyViewModel.Data, Source={StaticResource Locator}}" 
      SelectedIndex="{Binding MyViewModel.DataIndex, Source={StaticResource Locator}, Mode=OneWay}" 
      AutoGenerateColumns="True"/> 

Mon problème est qu'aucune des lignes sont sélectionnées sur mon DataGrid. Toutes les données s'affichent correctement dans la grille, mais la ligne n'est pas sélectionnée. J'ai vérifié les propriétés et a confirmé que la longueur du tableau est de 75 et DataIndex est un entier entre 0 et 74.


Il semble que la raison est parce que le DataGrid n'a pas fini de se charger lorsque la liaison est établie. Je peux le prouver en initialisant la liaison après le chargement du composant. Dans ce cas, tout fonctionne comme prévu et mon élément sélectionné est affiché correctement:

<DataGrid x:Name="MyDataGrid" Loaded="OnDataGridLoaded" 
      ItemsSource="{Binding MyViewModel.Data, Source={StaticResource Locator}}" 
      AutoGenerateColumns="True"/> 

private void OnDataGridLoaded(object sender, RoutedEventArgs e) 
{ 
    Binding b = new Binding("DataIndex"); 
    b.Source = Locator.MyViewModel.Data; 
    MyDataGrid.SetBinding(DataGrid.SelectedIndexProperty, b); 
} 

je préférerais ne pas avoir à le faire comme ça parce que, vous le savez, le code-behind. Alors est-il un moyen de résoudre ce problème en utilisant seulement XAML? Voici ce que j'ai essayé jusqu'à présent (dont aucun travaillé pour moi):

  • Reliure SelectedIndex à une propriété int sur mon ViewModel (comme indiqué ci-dessus)
  • Reliure SelectedItem à une propriété DataObject sur mon ViewModel (même résultat)
  • Liaison SelectedValue et SelectedPath à une propriété de mon DataObject (Cela a fonctionné pour la première fois seulement.) Le problème est que j'ai plusieurs instances de ce composant Datagrid, et pour une raison quelconque cela ne fonctionne que sur le premier instance)
  • Liaison à une ObservableCollection inste annonce d'un tableau (a essayé les trois méthodes ci-dessus avec un ObservableCollection et obtenu les mêmes résultats pour chacun)
  • Retarder la notification de modification en l'enveloppant dans un appel à Dispatcher.Invoke. Cela n'aide pas car le composant n'est pas immédiatement visible.
  • Création de la liaison dans XAML, puis mise à jour de la cible dans la fonction Loaded. MyDataGrid.GetBindingExpression(DataGrid.SelectedIndexProperty).UpdateTarget();
+0

@Clemens Merci, noté.Ce code est un résumé condensé de mon programme réel, dans lequel la source de DataGrid est un objet distinct de DataContext de UserControl. Mais malgré tout, tous les bons points. – Karmacon

+0

pourquoi n'appelez-vous pas l'événement 'setData' sur' Window.Loaded' pour la première fois. – esiprogrammer

+1

@EdPlunkett Désolé, j'ai oublié d'inclure cela dans ce code. Mais oui, j'ai mis la liaison à un sens – Karmacon

Répondre

0

Ma question originale manquait un élément d'information à l'origine du problème. Il semble qu'il y ait un bug WPF lorsque la source de liaison est un lien statique. Si je déplace la propriété DataIndex dans le DataContext du composant, cela fonctionnera correctement.

Je ne vais pas faire cela parce que les données sont partagées entre plusieurs instances. Je n'ai pas besoin d'avoir plusieurs instances des données, seulement le composant. Par conséquent, je vais juste corriger comme un bug de Microsoft, et utiliser le travail de code autour.

Je vais laisser la question ouverte, au cas où quelqu'un aurait une solution pour ce bug.