Utilisation de WPF DataGridComboBoxColumn avec MVVM-Binding to Property in ViewModel

j'utilise l'excellent MVVM Light Toolkit. Mon ViewModel expose:

public const string CourtCodesTypeCourtPropertyName = "CourtCodesTypeCourt";
private List<CourtType> _courtCodesTypes = new List<CourtType>();
public List<CourtType> CourtCodesTypeCourt
{
    get
    {
        return _courtCodesTypes;
    }

    set
    {
        if (_courtCodesTypes == value)
        {
            return;
        }

        var oldValue = _courtCodesTypes;
        _courtCodesTypes = value;

        // Update bindings and broadcast change using GalaSoft.MvvmLight.Messenging
        RaisePropertyChanged(CourtCodesTypeCourtPropertyName, oldValue, value, true);
    }
}

public const string CourtCodesPropertyName = "CourtCodes";
private List<Court> _courtCodes = null;
public List<Court> CourtCodes
{
    get
    {
        return _courtCodes;
    }

    set
    {
        if (_courtCodes == value)
        {
            return;
        }

        var oldValue = _courtCodes;
        _courtCodes = value;

        // Update bindings and broadcast change using GalaSoft.Utility.Messenging
        RaisePropertyChanged(CourtCodesPropertyName, oldValue, value, true);
    }
}

Le point de Vue a un DataGrid:

<DataGrid
      ItemsSource="{Binding CourtCodes, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
      AutoGenerateColumns="False"
      AlternatingRowBackground="{DynamicResource OffsetBrown}"
      AlternationCount="1" Margin="45,0">
   <DataGrid.Columns>
    <DataGridTextColumn Binding="{Binding Abbreviation, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
         Header="Abbreviation"
         Width="25*" />
    <DataGridTextColumn Binding="{Binding FullName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
         Header="Court"
         Width="75*" />
    <DataGridComboBoxColumn Header="CourtType" 
         ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.CourtCodesTypeCourt} TextBinding="{Binding CourtTypeDescription}""/>
   </DataGrid.Columns>
  </DataGrid>

le DataGrid a une source Itemss, comme vous pouvez le voir, de CourtCodes. Je veux que la colonne CourtType soit une liste de tous les types de Cour énumérés qui sont contenus dans CourtCodesTypeCourt. Je n'arrive pas à peupler la colonne Datagridcombox avec quoi que ce soit. La tentative échouée actuelle est je cherche à utiliser RelativeSource... ce que je fais mal?

en plus de ne pas fonctionner, les deux erreurs que je vois sont:

Système

.Windows.Erreur Dans Les Données: 4: Impossible trouver la source de liaison avec référence "RelativeSource FindAncestor, AncestorType= ' System.Windows.Fenêtre", Niveau d'ancêtre= '1". BindingExpression: Path=DataContext.Courcodestypecourt; DataItem=null; l'élément cible est "DataGridComboBoxColumn" (HashCode = 38771709); la propriété target de is 'ItemsSource' (type 'IEnumerable')

et

Système

.Windows.Erreur De Données: 40 : Erreur de chemin de BindingExpression: "CourtCodesTypeCourt" propriété non trouvé sur l '"objet" "Cour" (HashCode=38141773)". BindingExpression: Path=CourtCodesTypeCourt.CourtTypeDescription; DataItem= "Court" (HashCode=38141773); l'élément cible est "ComboBox" (Name="); la propriété cible est 'Text' (type 'String')

10
demandé sur Mike L 2010-08-25 08:51:28

3 réponses

DataGrid les définitions de colonne ne participent pas à l'arbre logique de la façon que vous attendez. C'est ridicule, mais la dernière fois que j'ai vérifié, vous devez faire quelque chose comme ça:

<DataGridComboBoxColumn Header="CourtType" SelectedItemBinding="{Binding Type}">
    <DataGridComboBoxColumn.ElementStyle>
        <Style TargetType="ComboBox">
            <Setter Property="ItemsSource" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.CourtCodesTypeCourt}"/>
            <Setter Property="IsReadOnly" Value="True"/>
        </Style>
    </DataGridComboBoxColumn.ElementStyle>
    <DataGridComboBoxColumn.EditingElementStyle>
        <Style TargetType="ComboBox">
            <Setter Property="ItemsSource" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.CourtCodesTypeCourt}"/>
        </Style>
    </DataGridComboBoxColumn.EditingElementStyle>
</DataGridComboBoxColumn>

vous remarquerez que j'ai aussi changé votre TextBinding en SelectedItemBinding . Je ne suis pas sûr que vous vouliez réellement un TextBinding , mais si vous voulez juste permettre à l'utilisateur de choisir entre la liste, alors SelectedItemBinding est probablement ce que vous voulez.

De plus, vos MV ne suivent pas exactement les meilleures pratiques. Vous utilisez List<T> au lieu de ObservableCollection<T> , et vous l'exposez comme List<T> plutôt que quelque chose de plus simple comme ICollection<T> .

28
répondu Kent Boogaart 2011-09-27 15:11:54

ici j'ai trouvé la réponse http://cinch.codeplex.com/discussions/239522

pour le DataGridComboBoxColumn vous devez créer une source statique de la source Itemsscomme:

<CollectionViewSource Source="{Binding Element=theView, Path=DataContext.ViewModelCollection1}" x:Key="ViewModelCollection1" />

et le lier à la DataGridComboBoxColumn avec ce qui suit:

ItemsSource="{Binding Source={StaticResource ViewModelCollection1}}"

c'est parce que les Colonnesde données ne font pas partie de l'arbre visuel.

et si vous voulez attacher sur un collection d'un élément du DataGrid vous devez régler le ItemsSource sur les deux styles:

<DataGridComboBoxColumn.ElementStyle>
    <Style TargetType="ComboBox">
        <Setter Property="ItemsSource" Value="{Binding Path=ModelCollection1}" />
    </Style> </DataGridComboBoxColumn.ElementStyle> <DataGridComboBoxColumn.EditingElementStyle>
    <Style TargetType="ComboBox">
        <Setter Property="ItemsSource" Value="{Binding Path=ModelCollection1}" />
    </Style> </DataGridComboBoxColumn.EditingElementStyle>
2
répondu Oyun 2017-01-24 10:31:43
-1
répondu SurfingSanta 2015-07-30 02:15:35