2010-08-25 12 views
10

Używam doskonałego zestawu narzędzi MVVM Light. Moje ViewModel uwidacznia:Korzystanie z WPF DataGridComboBoxColumn z MVVM - powiązanie z właściwością w 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 ma 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 ma ItemsSource, jak widać, od CourtCodes. Chcę, aby kolumna CourtType była rozwijana wszystkich wyliczonych CourtTypes, które są zawarte w CourtCodesTypeCourt. Dla mojego życia nie mogę zapełnić pola DataGridComboBoxColumn czymkolwiek. Obecna nieudana próba próbuje użyć RelativeSource ... co robię źle?

Ponadto nie działa, dwa błędy, które widzę są:

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

i

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

Odpowiedz

28

DataGrid definicje kolumn nie uczestniczą w logicznym drzewo na drodze można się spodziewać. To śmieszne, ale ostatnio sprawdziłem trzeba zrobić coś takiego:

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

Zauważysz Ja również zmienił swoją TextBinding do SelectedItemBinding. Nie jestem pewien, czy faktycznie zamierzałeś TextBinding, ale jeśli chcesz zezwolić użytkownikowi na wybór między listą, to prawdopodobnie chcesz, aby to było SelectedItemBinding.

Ponadto Twoje maszyny wirtualne nie są zgodne z najlepszymi praktykami. Używasz List<T> zamiast ObservableCollection<T>, a ujawniasz to jako List<T> zamiast czegoś prostszego, takiego jak ICollection<T>.

+0

Dzięki za twoją pomoc, Kent ... to zdecydowanie mnie zbliża. Zgadzam się ... to niedorzeczne, że trzeba uciec się do tego rodzaju składni. Walczę. Teraz mam obiekty CourtType wypełniające DataGridComboBoxColumn, ale w ramach tej składni, jak kontrolować wyświetlany tekst? Obecnie wyświetla nazwę typu, a nie właściwość CourtTypeDescription. Po drugie, doceniam Twoją opinię na temat najlepszych praktyk ...Mógłbym, być może błędnie, odnieść wrażenie, że MVVM Light Toolkit przekształcił utworzone przez mvvminpc właściwości w ObservableCollections ... czy ja też na tym nie polega? –

+0

Zignoruj ​​pytanie o najlepszą praktykę ObservableCollections ... Przetestowałem to nieco i widzę wartość. Możliwość dołączenia do zdarzenia CollectionChanged wydaje się warta tego na własną odpowiedzialność. Mogę użyć przeskoków na składni DataGridComboBoxColumn ... jeszcze raz dziękuję za pomoc! –

+0

@Mike: powinieneś być w stanie ustawić 'DisplayMemberPath =" CourtTypeDescription "' na twoim 'DataGridComboBoxColumn'. –

2

Tutaj znalazłem odpowiedź http://cinch.codeplex.com/discussions/239522

Dla DataGridComboBoxColumn trzeba stworzyć StaticRecource z ItemsSource jak:

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

i powiązać go do DataGridComboBoxColumn z następujących powodów:

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

To dlatego, że DataGridColumns nie są częścią wizualnego drzewa.

A jeśli chcesz się związać na zbiór pozycji w DataGrid trzeba ustawić ItemsSource ciągu dwóch stylach:

<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> 
Powiązane problemy