2011-10-10 11 views
45

Net 3.5Bind datagrid visibilità colonna MVVM

So che le colonne non eredita il DataContext e leggendo altri post ho pensato che questo avrebbe funzionato:

Visibility="{Binding RelativeSource={x:Static RelativeSource.Self}, 
        Path=(FrameworkElement.DataContext).IsColumnNameVisible, 
        Converter={StaticResource boolToVisConverter}}" 

Tuttavia ovviamente doesn' t .. La finestra di output non si lamenta, sembra che la risorsa ho trovato, ma la proprietà viewmodel è più recente chiamata.

Questo è l'intero DG:

<tk:DataGrid           
      VirtualizingStackPanel.IsVirtualizing="False"           
      Grid.Column="0" 
      AlternationCount="2" 
      AreRowDetailsFrozen="True" 
      AutoGenerateColumns="False" 
      Background="Transparent" 
      BorderThickness="0" 
      CanUserAddRows="False" 
      CanUserReorderColumns="True" 
      CanUserResizeRows="False" 
      GridLinesVisibility="None" 
      ItemsSource="{Binding Employees}" 
      SelectionMode="Single" 
      ColumnHeaderStyle="{StaticResource columnHeaderStyle}" 
      RowHeaderStyle="{StaticResource rowHeaderStyle}" 
      CellStyle="{StaticResource cellStyle}" 
      RowStyle="{StaticResource rowStyle}" 
      ContextMenu="{StaticResource columnHeaderContextMenu}"> 
    <tk:DataGrid.Resources> 
     <ContextMenu x:Key="columnHeaderContextMenu" ItemsSource="{Binding ColumnHeaderContextMenuItems}" /> 
     <Style TargetType="{x:Type ScrollBar}"> 
      <Setter Property="Background" Value="Transparent"/> 
     </Style>          
     <Style TargetType="{x:Type tk:DataGridColumnHeader}"> 
      <Setter Property="Background" Value="Transparent"/> 
     </Style> 
    </tk:DataGrid.Resources> 
    <tk:DataGrid.Triggers> 
     <EventTrigger RoutedEvent="tk:DataGridRow.MouseDoubleClick"> 
      <EventTrigger.Actions> 
       <BeginStoryboard Storyboard="{StaticResource showDetailGrid}"/> 
      </EventTrigger.Actions> 
     </EventTrigger> 
    </tk:DataGrid.Triggers> 
    <tk:DataGrid.Columns> 
     <tk:DataGridTextColumn IsReadOnly="True" Header="test" Binding="{Binding Name, Mode=OneWay}" Visibility="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=(FrameworkElement.DataContext).IsColumnNameVisible, Converter={StaticResource boolToVisConverter}}" /> 
    </tk:DataGrid.Columns> 
</tk:DataGrid> 

Ho letto praticamente ogni singola soluzione a questo problema e non funziona niente ..

+0

Se trovi la tua domanda un po 'poco chiara. Stai solo cercando di rendere visibile o invisibile una colonna di dati a seconda della proprietà ViewModel associata? – ChrisBD

+0

Modifica il tuo ContextMenu in '' - non c'è da stupirsi che la tua finestra DataContext non sia raggiungibile. –

+0

@ ChrisBD: Sì, questa è l'idea. Il puntello VM viene impostato tramite il datacontext. – jrb

risposta

95

DataGridColumn s non fanno parte della struttura ad albero visuale in modo che non siano collegati al contesto dati di DataGrid.

Per loro collegare insieme usano approccio elemento procura come questo ...

  1. Aggiungi un proxy FrameworkElement nel tuo pannello di Resources antenato.
  2. Ospitarlo in un invisibile ContentControl associato a Content.
  3. Utilizzare questo ProxyElement come StaticResource per l'origine del contesto dati nel bind di visibilità.

    <StackPanel> 
        <StackPanel.Resources> 
         <local:BooleanToVisibilityConverter 
           x:Key="BooleanToVisibilityConverter" /> 
    
         <FrameworkElement x:Key="ProxyElement" 
             DataContext="{Binding}"/> 
        </StackPanel.Resources> 
        <ContentControl Visibility="Collapsed" 
           Content="{StaticResource ProxyElement}"/> 
        <DataGrid AutoGenerateColumns="False"> 
         <DataGrid.Columns> 
          <DataGridTextColumn 
            Visibility="{Binding DataContext.IsTextColumnVisibile, 
                 Source={StaticResource ProxyElement}, 
                 Converter={StaticResource 
                  BooleanToVisibilityConverter}}" 
            Binding="{Binding Text}"/> 
         </DataGrid.Columns> 
        </DataGrid> 
    </StackPanel> 
    

parte DataGridColumn, il metodo di cui sopra funziona anche grande per collegare DataContext a Popup s e ContextMenu s (cioè qualsiasi elemento che non è collegato all'albero visivo).

Utenti Silverlight

impostazione Purtroppo contenuto di controlli contenuti con tutti gli elementi quadro non è consentito in Silverlight. Quindi la soluzione sarebbe (questo è solo un codice di orientamento per Silverlight) ...

  1. modificare il quadro elemento di risorsa per qualcosa di leggero come un Textblock. (Silverlight non consente specifica risorsa statica di FrameworkElement tipo.)

    <StackPanel.Resources> 
        <TextBlock x:Key="MyTextBlock" /> 
    
  2. Scrivi una proprietà associata a tenere blocco di testo contro il controllo dei contenuti.

    <ContentControl Visibility="Collapsed" 
           local:MyAttachedBehavior.ProxyElement="{StaticResource MyTextBlock}" /> 
    
  3. Nel gestore di eventi cambiato proprietà di dipendenza in allegato, impostare la legano il contesto dati del controllo dei contenuti per il blocco di testo del.

Quindi in questo modo il blocco di testo potrebbe non essere collegato alla struttura ad albero visuale, ma sarà probabilmente essere consapevoli del contesto dati di modifiche.

Spero che questo aiuti.

+0

Ottenuto un'eccezione quando deseleziona e riseleziona: l'elemento specificato è già il figlio logico di un altro elemento. Scollegalo prima. Sai perché? – jrb

+0

Potrebbe essere il tuo 'ContextMenu' ... può essere collegato solo a un genitore. –

+0

Modificato ContextMenu in DataGrid CM non DGColumnHeader CM ma non è stato di aiuto. Lo uso su più colonne se questo è importante .. – jrb

Problemi correlati