2010-08-25 2 views
10

Я использую отличный MVVM Light Toolkit. Мой ViewModel предоставляет:Использование WPF DataGridComboBoxColumn с MVVM - привязка к свойству в 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); 
    } 
} 

The View есть 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> 

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

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

System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Window', AncestorLevel='1''. BindingExpression:Path=DataContext.CourtCodesTypeCourt; DataItem=null; target element is 'DataGridComboBoxColumn' (HashCode=38771709); target property is 'ItemsSource' (type 'IEnumerable')

и

System.Windows.Data Error: 40 : BindingExpression path error: 'CourtCodesTypeCourt' property not found on 'object' ''Court' (HashCode=38141773)'. BindingExpression:Path=CourtCodesTypeCourt.CourtTypeDescription; DataItem='Court' (HashCode=38141773); target element is 'ComboBox' (Name=''); target property is 'Text' (type 'String')

ответ

28

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

+0

Спасибо за вашу помощь, Кент ... это определенно приближает меня. Я согласен ... смешно прибегать к подобному синтаксису. Я пытаюсь. У меня теперь есть объекты CourtType, заполняющие DataGridComboBoxColumn, но в этом синтаксисе, как мне управлять отображаемым текстом? В настоящее время он содержит имя типа, а не свойство CourtTypeDescription. Во-вторых, я ценю ваши отзывы о лучших практиках ...Возможно, я ошибался под впечатлением того, что MVVM Light Toolkit создал mvvminpc-созданный объект в ObservableCollections ... я тоже на этом? –

+0

Игнорируйте вопрос об оптимальной практике ObservableCollections ... Я немного проверил его и посмотрел на значение. Возможность подключиться к событию CollectionChanged кажется достойным того, что это по праву. Я могу использовать подталкивание к синтаксису DataGridComboBoxColumn ... еще раз спасибо за вашу помощь! –

+0

@Mike: вы должны просто установить 'DisplayMemberPath =" CourtTypeDescription "' на свой 'DataGridComboBoxColumn'. –

2

Здесь я нашел ответа 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}}" 

Thats, потому что 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>