J'ai un ComboBox qui ne semble pas mettre à jour le SelectedItem/SelectedValue.
La ComboBox ItemsSource est liée à une propriété d'une classe ViewModel qui liste un ensemble d'entrées de répertoire RAS sous la forme d'une CollectionView, puis j'ai lié (à des moments différents) les SelectedItem ou SelectedValue à une autre propriété du ViewModel. J'ai ajouté un MessageBox dans la commande de sauvegarde pour déboguer les valeurs définies par la liaison de données, mais la liaison SelectedItem/SelectedValue n'est pas définie.
La classe ViewModel ressemble à ceci :
public ConnectionViewModel
{
private readonly CollectionView _phonebookEntries;
private string _phonebookeEntry;
public CollectionView PhonebookEntries
{
get { return _phonebookEntries; }
}
public string PhonebookEntry
{
get { return _phonebookEntry; }
set
{
if (_phonebookEntry == value) return;
_phonebookEntry = value;
OnPropertyChanged("PhonebookEntry");
}
}
}
La collection _phonebookEntries est initialisée dans le constructeur à partir d'un objet métier. Le XAML de la ComboBox ressemble à ceci :
<ComboBox ItemsSource="{Binding Path=PhonebookEntries}"
DisplayMemberPath="Name"
SelectedValuePath="Name"
SelectedValue="{Binding Path=PhonebookEntry}" />
Je ne suis intéressé que par la valeur réelle de la chaîne affichée dans la ComboBox, et non par les autres propriétés de l'objet, car c'est la valeur que je dois transmettre à RAS lorsque je veux établir la connexion VPN, d'où le fait que DisplayMemberPath et SelectedValuePath sont tous deux la propriété Name du ConnectionViewModel. La ComboBox se trouve dans un DataTemplate appliqué à un ItemsControl sur une fenêtre dont le DataContext a été défini sur une instance de ViewModel.
La ComboBox affiche correctement la liste des éléments, et je peux en sélectionner un dans l'interface utilisateur sans problème. Cependant, lorsque j'affiche la boîte de message de la commande, la propriété PhonebookEntry contient toujours la valeur initiale, et non la valeur sélectionnée dans la ComboBox. Les autres instances de TextBox se mettent à jour correctement et s'affichent dans la boîte de message.
Qu'est-ce que je rate avec la liaison de données de la ComboBox ? J'ai fait beaucoup de recherches et je n'ai pas trouvé ce que je faisais de mal.
C'est le comportement que je constate, mais il ne fonctionne pas pour une raison quelconque dans mon contexte particulier.
J'ai un MainWindowViewModel qui possède une CollectionView de ConnectionViewModels. Dans le code-behind du fichier MainWindowView.xaml, j'ai défini le DataContext sur le MainWindowViewModel. Le fichier MainWindowView.xaml comporte un ItemsControl lié à la collection de ConnectionViewModels. J'ai un DataTemplate qui contient la ComboBox ainsi que d'autres TextBoxes. Les boîtes de texte sont liées directement aux propriétés du ConnectionViewModel en utilisant Text="{Binding Path=ConnectionName}".
public class ConnectionViewModel : ViewModelBase
{
public string Name { get; set; }
public string Password { get; set; }
}
public class MainWindowViewModel : ViewModelBase
{
// List<ConnectionViewModel>...
public CollectionView Connections { get; set; }
}
Le code-behind XAML :
public partial class Window1
{
public Window1()
{
InitializeComponent();
DataContext = new MainWindowViewModel();
}
}
Puis XAML :
<DataTemplate x:Key="listTemplate">
<Grid>
<ComboBox ItemsSource="{Binding Path=PhonebookEntries}"
DisplayMemberPath="Name"
SelectedValuePath="Name"
SelectedValue="{Binding Path=PhonebookEntry}" />
<TextBox Text="{Binding Path=Password}" />
</Grid>
</DataTemplate>
<ItemsControl ItemsSource="{Binding Path=Connections}"
ItemTemplate="{StaticResource listTemplate}" />
Les TextBox se lient tous correctement, et les données circulent entre eux et le ViewModel sans problème. C'est seulement la ComboBox qui ne fonctionne pas.
Vous avez raison dans votre hypothèse concernant la classe PhonebookEntry.
Je suppose que le DataContext utilisé par mon DataTemplate est automatiquement défini par la hiérarchie de liaison, de sorte que je n'ai pas à le définir explicitement pour chaque élément du ItemsControl. Cela me semble un peu stupide.