Je suis un débutant sur WPF et j'essaie de lier les éléments d'un ComboBox à un ObservableCollection
J'ai utilisé ce code:
XAML
<Window x:Class="comboBinding2.MainWindow"
xmlns="http://schemas.Microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.Microsoft.com/winfx/2006/xaml"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
Title="MainWindow" Height="350" Width="525">
<Grid>
<ComboBox x:Name="cmbTest" ItemsSource="{Binding Path=cmbContent}" Width="200" VerticalAlignment="Center" HorizontalAlignment="Center" />
</Grid>
</Window>
C #
public MainWindow()
{
cmbTest.ItemsSource = cmbContent;
cmbContent.Add("test 1");
cmbContent.Add("test 2");
InitializeComponent();
}
public ObservableCollection<string> cmbContent { get; set; }
Je n'obtiens aucune erreur sur ce code jusqu'à ce que j'essaie de déboguer, il renvoie l'erreur:
TargetInvocationError
Une exception non gérée de type 'System.Reflection.TargetInvocationException' s'est produite dans PresentationFramework.dll
Quelqu'un peut-il me dire ce que je fais mal?
Il y a quelques problèmes avec votre implémentation actuelle. Comme d'autres l'ont indiqué, votre liste est actuellement NULL
et le DataContext
de la fenêtre n'est pas défini.
Cependant, je recommanderais (surtout depuis que vous venez de commencer à utiliser WPF) d'apprendre à faire la liaison de la manière la plus "correcte", en utilisant MVVM
.
Voir l'exemple simplifié ci-dessous:
Tout d'abord, vous voulez définir le DataContext
de votre Window
. Cela permettra au XAML
de 'voir' les propriétés dans votre ViewModel
.
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new ViewModel();
}
}
Ensuite, configurez simplement une classe ViewModel
qui contiendra tous les Window's
éléments de liaison, tels que:
public class ViewModel
{
public ObservableCollection<string> CmbContent { get; private set; }
public ViewModel()
{
CmbContent = new ObservableCollection<string>
{
"test 1",
"test 2"
};
}
}
Enfin, mettez à jour votre XAML
pour que le chemin de liaison corresponde à la collection:
<Grid>
<ComboBox Width="200"
VerticalAlignment="Center"
HorizontalAlignment="Center"
x:Name="cmbTest"
ItemsSource="{Binding CmbContent}" />
</Grid>
public MainWindow()
{
InitializeComponent();
cmbContent=new ObservableCollection<string>();
cmbContent.Add("test 1");
cmbContent.Add("test 2");
cmbTest.ItemsSource = cmbContent;
}
public ObservableCollection<string> cmbContent { get; set; }
Le code ci-dessus n'utilise aucune liaison, c'est-à-dire qu'il ne sert à rien de lier le Combobox's
ItemSource
, si vous ne souhaitez pas utiliser la liaison, vous devez
First: Définissez le DataContext à partir du CodeBehind (ViewModel) en utilisant:
this.DataContext=this;
ou depuis le Xaml:
DataContext="{Binding RelativeSource={RelativeSource Self}}">
Second: utilisez la liaison dans ItemSource comme vous l'avez fait ItemsSource="{Binding Path=cmbContent}"
vous pouvez également envisager d'utiliser INotifyPropertyChanged
Interface si vous souhaitez notifier l'interface utilisateur en cas de modification d'une propriété
cmbContent
est null car vous ne le définissez jamais sur rien. Je suppose que l'erreur est en fait un NullReferenceException
, mais elle apparaît comme TargetInvocationException
car elle est dans le constructeur d'une vue.
En outre, vous définissez deux fois le ItemsSource
du ComboBox
(une fois dans la liaison, une fois dans le constructeur). Vous n'avez pas besoin de faire ça. Choisissez-en un. Votre liaison ne fonctionnera pas comme elle est écrite (car le DataContext
n'est pas défini), vous devez donc soit le faire dans le code, soit configurer le DataContext
(comme suggéré par Nadia).