2010-08-25 84 views
10

我使用了優秀的MVVM Light Toolkit。我的視圖模型公開:在MVVM中使用WPF DataGridComboBoxColumn - 在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:

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

數據網格有一個ItemsSource時,你可以看到CourtCodes的。我希望CourtType列是CourtCodesTypeCourt中包含的所有列舉的CourtType的下拉列表。對於我的生活,我似乎無法用任何東西填充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> 

你會發現我也改變了你的TextBindingSelectedItemBinding。我不確定你是否真的想要TextBinding,但如果你只是想讓用戶在列表中進行選擇,那麼SelectedItemBinding可能就是你想要的。

另外,您的虛擬機並不完全遵循最佳實踐。您使用的是List<T>而不是ObservableCollection<T>,並且您將其公開爲List<T>而不是簡單的東西,例如ICollection<T>

+0

感謝您的幫助,肯特......這絕對讓我更加接近。我同意......不得不訴諸這種語法是荒謬的。我正在掙扎。 我現在有了填充DataGridComboBoxColumn的CourtType對象,但在這個語法中,我該如何控制顯示的文本?目前它列出了類型名稱,而不是CourtTypeDescription屬性。其次,我感謝您對最佳做法的反饋......我可能錯誤地認爲,MVVM Light Toolkit使mvvminpc片段創建了ObservableCollections中的特性......我是否也這麼做? – 2010-08-25 21:06:57

+0

忽略ObservableCollections最佳實踐問題...我測試了一下並查看了值。掛鉤到CollectionChanged事件的能力似乎非常值得它本身。 我可以使用DataGridComboBoxColumn的語法輕推...再次感謝您的幫助! – 2010-08-26 04:07:28

+0

@Mike:你應該可以在你的DataGridComboBoxColumn上設置DisplayMemberPath =「CourtTypeDescription」。 – 2010-08-26 08:52:10

2

在這裏,我已經找到答案http://cinch.codeplex.com/discussions/239522

對於DataGridComboBoxColumn你要創建的ItemsSource的StaticRecource,如:

<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> 
相關問題