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();
@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
pourquoi n'appelez-vous pas l'événement 'setData' sur' Window.Loaded' pour la première fois. – esiprogrammer
@EdPlunkett Désolé, j'ai oublié d'inclure cela dans ce code. Mais oui, j'ai mis la liaison à un sens – Karmacon