2010-08-25 7 views
10

Estoy usando el excelente MVVM Light Toolkit. Mi ViewModel expone:Usando WPF DataGridComboBoxColumn con MVVM - Enlace a la propiedad en 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); 
    } 
} 

la vista tiene una cuadrícula de datos:

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

La cuadrícula de datos tiene una ItemsSource, como se puede ver, de CourtCodes. Quiero que la columna CourtType sea un menú desplegable de todos CourtTypes enumerados que se encuentran dentro de CourtCodesTypeCourt. Por mi vida, parece que no puedo llenar DataGridComboBoxColumn con nada. El intento fallido actual está buscando usar RelativeSource ... ¿qué estoy haciendo mal?

Además de no trabajo, los dos errores que veo son:

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

y

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

Respuesta

28

DataGrid definiciones de columna no participan en el árbol lógico en la forma en que se puede esperar. Es ridículo, pero yo sepa lo que tiene que hacer algo como esto:

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

Se dará cuenta de que también he cambiado su TextBinding a un SelectedItemBinding. No estoy seguro de si realmente pretendía un TextBinding, pero si solo desea permitir que el usuario seleccione entre la lista, es probable que SelectedItemBinding sea lo que quiere.

Además, sus máquinas virtuales no siguen exactamente las mejores prácticas. Estás usando List<T> en lugar de ObservableCollection<T>, y lo estás exponiendo como List<T> en lugar de algo más simple como ICollection<T>.

+0

Gracias por tu ayuda, Kent ... esto definitivamente me acerca. Estoy de acuerdo ... es ridículo tener que recurrir a este tipo de sintaxis. Estoy luchando. Ahora tengo los objetos CourtType que pueblan DataGridComboBoxColumn, pero dentro de esta sintaxis, ¿cómo controlo el texto mostrado? Actualmente enumera el nombre del tipo, no su propiedad CourtTypeDescription. En segundo lugar, agradezco sus comentarios sobre las mejores prácticas ...Yo estaba, quizás erróneamente, bajo la impresión de que MVVM Light Toolkit creó propiedades de mvvminpc en Snippet en ObservableCollections ... ¿Estoy fuera de eso también? –

+0

Ignore la pregunta de mejores prácticas de ObservableCollections ... Lo probé un poco y veo el valor. La posibilidad de engancharse al evento CollectionChanged parece valer la pena por sí misma. Podría usar un empujón en la sintaxis para DataGridComboBoxColumn ... ¡gracias de nuevo por su ayuda! –

+0

@Mike: solo debe poder establecer 'DisplayMemberPath =" CourtTypeDescription "' en su 'DataGridComboBoxColumn'. –

2

Aquí he encontrado respuesta http://cinch.codeplex.com/discussions/239522

Para el DataGridComboBoxColumn usted tiene que crear un StaticRecource del ItemsSource como:

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

y enlazarlo a la DataGridComboBoxColumn con lo siguiente:

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

Eso es porque DataGridColumns no es una parte del árbol visual.

Y si desea enlazar en una colección de un elemento de la cuadrícula de datos que tienen que establecer el ItemsSource lo largo de los dos estilos:

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