2010-08-25 19 views
10

ich die hervorragende MVVM Light Toolkit verwenden. Mein Ansichtsmodell macht:- Bindung an Immobilien in Ansichtsmodell

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

Das Datagrid eine Itemssource hat, wie Sie, von CourtCodes sehen können. Ich möchte die CourtType Spalte ein Dropdown aller aufgezählten CourtTypes sein, die in CourtCodesTypeCourt enthalten sind. Für das Leben von mir, ich kann nicht scheinen, um die DataGridComboBoxColumn mit etwas zu füllen. Der aktuelle fehlgeschlagene Versuch versucht RelativeSource zu verwenden ... was mache ich falsch?

Zusätzlich arbeiten nicht, die beiden Fehler ich sehe, sind:

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

und

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

Antwort

28

DataGrid Spaltendefinitionen Sie würden nicht erwarten, in der logischen Struktur in der Art und Weise teilnehmen. Es ist lächerlich, aber ich zuletzt überprüft Sie, so etwas zu tun haben:

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

Sie werden bemerken, ich auch Ihre TextBinding zu einem SelectedItemBinding geändert haben. Ich bin mir nicht sicher, ob Sie tatsächlich ein TextBinding gedacht, aber wenn Sie nur der Benutzer, um zwischen der Liste zulassen wollen, dann SelectedItemBinding ist wahrscheinlich, was Sie wollen.

Auch Ihre VMs nicht genau, Best Practices folgen. Sie verwenden List<T> anstelle von ObservableCollection<T>, und Sie stellen es als List<T> statt etwas einfacheres wie ICollection<T>.

+0

Danke für deine Hilfe, Kent ... das bringt mich definitiv näher. Ich stimme zu ... es ist lächerlich, auf diese Art von Syntax zurückgreifen zu müssen. Ich kämpfe. Ich habe jetzt die CourtType-Objekte, die die DataGridComboBoxColumn füllen, aber wie kann ich den angezeigten Text innerhalb dieser Syntax steuern? Derzeit listet es den Typnamen auf, nicht seine CourtTypeDescription-Eigenschaft. Zweitens, ich freue mich über Ihr Feedback zu Best Practices ...Ich hatte vielleicht fälschlicherweise den Eindruck, dass das MVVM Light Toolkit mvvminpc-Snippets in ObservableCollections erstellt hat ... bin ich auch dran? –

+0

Ignoriere die Best Practice-Frage von ObservableCollections ... Ich habe es ein wenig getestet und den Wert angezeigt. Die Möglichkeit, sich in das CollectionChanged-Ereignis einzuklinken, lohnt sich auf jeden Fall. Ich könnte einen Anstoß auf die Syntax für die DataGridComboBoxColumn ... Danke nochmal für Ihre Hilfe! –

+0

@Mike: Sie sollten einfach 'DisplayMemberPath =" CourtTypeDescription "' auf Ihrer 'DataGridComboBoxColumn' setzen können. –

2

Hier habe ich gefunden Antwort http://cinch.codeplex.com/discussions/239522

Für die DataGridComboBoxColumn Sie haben eine StaticRecource der Itemssource wie zu erstellen:

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

und an die DataGridComboBoxColumn binden mit folgenden:

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

das ist, weil die Datagridcolumns ist nicht Teil der visuellen Struktur.

Und wenn Sie auf einer Sammlung von einem Element des Datagrid binden wollen, müssen Sie die Itemssource über die zwei Arten eingestellt werden:

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