web-dev-qa-db-fra.com

Liaison WPF ComboBox ItemsSource

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?

7
LUXS

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>
14
d.moncada
   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'sItemSource, 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é

3
ELH

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).

1
Tim