Использование WPF DataGridComboBoxColumn с MVVM - привязка к свойству во ViewModel - PullRequest
11 голосов
/ 25 августа 2010

Я использую отличный MVVM Light Toolkit. Моя ViewModel выставляет:

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);
    }
}

Представление имеет сетку данных:

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

DataGrid, как вы можете видеть, имеет ItemSource из CourtCodes. Я хочу, чтобы столбец CourtType был выпадающим списком всех перечисленных типов CourtType, которые содержатся в CourtCodesTypeCourt. Насколько я могу судить, я не могу заполнить DataGridComboBoxColumn чем-либо. Текущая неудачная попытка использовать RelativeSource ... что я делаю не так?

В дополнение к тому, что я не работаю, я вижу две ошибки:

System.Windows.Data Ошибка: 4: невозможно найти источник для привязки со ссылкой 'RelativeSource FindAncestor, AncestorType = 'System.Windows.Window', AncestorLevel = '1'». BindingExpression: Path = DataContext.CourtCodesTypeCourt; DataItem = NULL; целевой элемент 'DataGridComboBoxColumn' (HashCode = 38771709); целевое свойство is 'ItemsSource' (тип 'IEnumerable')

и

System.Windows.Data Ошибка: 40: Ошибка пути BindingExpression: Свойство 'CourtCodesTypeCourt' не найдено на «объекте» «суд» (HashCode = 38141773). BindingExpression: Path = CourtCodesTypeCourt.CourtTypeDescription; DataItem = 'Court' (HashCode = 38141773); целевой элемент - «ComboBox» (Имя = ''); целевое свойство 'Текст' (введите 'String')

Ответы [ 3 ]

28 голосов
/ 25 августа 2010

DataGrid определения столбцов не участвуют в логическом дереве так, как вы ожидаете. Это смешно, но в последний раз я проверял, что вы должны сделать что-то вроде этого:

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

Вы заметите, что я также изменил ваш TextBinding на SelectedItemBinding. Я не уверен, что вы на самом деле намеревались TextBinding, но если вы просто хотите позволить пользователю выбирать между списком, то SelectedItemBinding, вероятно, то, что вы хотите.

Кроме того, ваши виртуальные машины не совсем соответствуют рекомендациям. Вы используете List<T> вместо ObservableCollection<T> и выставляете его как List<T>, а не как что-то более простое, например ICollection<T>.

3 голосов
/ 06 июня 2013

Здесь я нашел ответ http://cinch.codeplex.com/discussions/239522

Для столбца DataGridComboBoxColumn необходимо создать StaticRecource для ItemsSource, например:

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

, и связать его с DataGridComboBoxColumn следующим образом:

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

Это потому, что DataGridColumns не являются частью визуального дерева.

И если вы хотите связать коллекцию с элементом DataGrid, вы должны установить ItemsSource поверхдва стиля:

<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>
0 голосов
/ 30 июля 2015

Проверьте этот блестящий урок / пример: https://code.msdn.microsoft.com/windowsdesktop/Best-ComboBox-Tutorial-5cc27f82

...