2012-11-05 14 views
6

Ho un ItemsControl in XAML dove sto visualizzando un expander per ogni gruppo in modo da poter espandere/comprimere il gruppo. Voglio mantenere lo stato della proprietà IsExpanded (e potenzialmente altre impostazioni relative alla visualizzazione dell'intestazione del gruppo). Normalmente hai solo una classe con le proprietà su di essa e ti leghi a questo. Tuttavia, il contesto dati per il gruppo è CollectionViewGroup. Ora questa classe non è molto utile in quanto ti dà solo la proprietà Name e gli elementi nel gruppo (che va bene se vuoi solo un'intestazione e magari visualizzare una sorta di metrica in base al numero di elementi nel gruppo o alla loro contenuto ma non se vuoi solo memorizzare dati personalizzati sullo stato dell'intestazione dell'interfaccia di gruppo). Quello che mi piacerebbe fare è derivare da questa classe e aggiungere altre proprietà alla mia classe derivata e associarla a quella. Ma non sembra essere un modo semplice per farlo. Tutti i dettagli della generazione di gruppo sembrano essere nascosti nelle classi interne, il che è molto frustrante. Qualcuno ha seguito il percorso di implementazione di ICollectionView (e quindi presumibilmente tutte le altre classi correlate)? Sembra un enorme lavoro replicare tutto in ListCollectionView solo per poter creare una classe personalizzata CollectionViewGroup e collegarla a quella! Grazie.Come associare dati personalizzati a CollectionViewGroup?

risposta

0

Un approccio semplice sarebbe quello di avvolgere il CollectionViewGroup in un'altra classe ViewModel che fornisce le proprietà di visualizzazione aggiuntive necessarie come IsExpanded. Una lezione che ho imparato a mio modo non era quella di piegare xaml/view in modo che corrispondesse ai dati aziendali. Piuttosto piegare/avvolgere o convertire i dati aziendali per soddisfare i requisiti dell'interfaccia utente.

+3

Puoi spiegare il tuo punto con un esempio? –

1

Un approccio consiste nell'utilizzare uno MultiBinding per trovare o calcolare i dati personalizzati e il bind-time.

Ho fatto un DataGrid con gruppi che mostra nell'intestazione somma delle voci valore specifico nel gruppo, per aggiornare questa somma quando Articoli gruppo modifiche ho fatto un multivalore vincolante con un convertitore più valori, la rilegatura il multivalore con ItemCount la proprietà consente di ricevere una notifica quando le voci del gruppo cambiano e quindi di aggiornare la somma e visualizzare il valore del newsum.

Ecco il codice per la classe convertitore multivalore:

Public Class UserBalanceConverter 
Implements IMultiValueConverter 

Private Function GetSubTotal(ByVal obj As CollectionViewGroup) As String 

    Dim total As Decimal 
    For Each objItem As Object In obj.Items 
     If TypeOf objItem Is Account Then 
      Dim a As Account = DirectCast(objItem, Account) 
      Dim rate As Decimal = 1 
      rate = 1/ExchangeRatesInfo.GetExchangeRate(a.currencyCode.ToString) 

      total += a.Balance * rate 
     Else 
      total += GetSubTotal(objItem) 
     End If 
    Next 

    Return total.ToString("C") 
End Function 

Public Function Convert(ByVal value() As Object, 
         ByVal targetType As System.Type, 
         ByVal parameter As Object, 
         ByVal culture As System.Globalization.CultureInfo) _ 
     As Object Implements System.Windows.Data.IMultiValueConverter.Convert 

    Dim cvg As CollectionViewGroup = CType(value(1), CollectionViewGroup) 

    Return GetSubTotal(cvg) 

End Function 


Public Function ConvertBack(ByVal value As Object, 
          ByVal targetType() As System.Type, 
          ByVal parameter As Object, 
          ByVal culture As System.Globalization.CultureInfo) _ 
     As Object() Implements System.Windows.Data.IMultiValueConverter.ConvertBack 

    Throw New NotImplementedException 

End Function 

End Class 

Poi in XAML si utilizza il convertitore multivalore in uno stile utilizzato per GroupItem:

<Style TargetType ="{x:Type GroupItem}" x:Key="UserGroupHeaderStyle"> 
      <Setter Property="Template"> 
       <Setter.Value> 
        <ControlTemplate TargetType="{x:Type GroupItem}"> 
         <Expander x:Name="exp" IsExpanded="False"> 
          <Expander.Header> 
           <StackPanel > 
            <TextBlock Text="{Binding Name}" /> 
            <StackPanel Orientation="Horizontal" > 
             <TextBlock Text="{Binding ItemCount}"> 
             <TextBlock Text=" "/> 
             <TextBlock Text="items" /> 
             <TextBlock Text=" "/> 
             <TextBlock Text="Balance: " /> 
             <TextBlock> 
              <TextBlock.Text> 
               <MultiBinding Converter="{StaticResource UserBalanceConverter}"> 
                <Binding Path="ItemCount"/> 
                <Binding /> 
               </MultiBinding> 
              </TextBlock.Text> 
             </TextBlock> 
            </StackPanel> 
           </StackPanel> 
          </Expander.Header> 
          <ItemsPresenter /> 
         </Expander> 
        </ControlTemplate> 
       </Setter.Value> 
      </Setter> 
     </Style> 

Finitura con l'applicazione lo stile al vostro DataGrid:

<DataGrid.GroupStyle> 
    <GroupStyle ContainerStyle="{StaticResource UserGroupHeaderStyle}"> 
      <GroupStyle.Panel> 
        <ItemsPanelTemplate> 
          <DataGridRowsPresenter/> 
        </ItemsPanelTemplate> 
      </GroupStyle.Panel> 
    </GroupStyle> 
</DataGrid.GroupStyle> 

Inoltre, non dimenticare di dichiarare la classe di conversione i n la sezione risorse del tuo XAML:

<ResourceDictionary> 
     <ResourceDictionary.MergedDictionaries> 
      <local:UserBalanceConverter x:Key="UserBalanceConverter"/> 
     </ResourceDictionary.MergedDictionaries> 
    </ResourceDictionary> 

Et Voilà! Esso funziona magicamente!

HTH

+0

come risponde la domanda degli OP? ha chiesto come mantenere il valore IsExpanded e non generare metriche dagli elementi che ha escluso nella domanda. – Firo

0

sono stato in grado di risolvere esattamente questo problema (vale a dire il legame con IsExpanded) utilizzando un approccio che è in qualche modo simile al suggerimento di Cédric, ma in un modo apparentemente più MVVM:

<ControlTemplate TargetType="GroupItem"> 
    <TreeViewItem IsExpanded="{Binding Items[0].IsGroupExpanded, Mode=TwoWay}"> 
     <TreeViewItem.Header> 
      <TextBlock Text="{Binding Name}" /> 
     </TreeViewItem.Header> 
     <TreeViewItem.Items> 
      <ItemsPresenter /> 
     </TreeViewItem.Items> 
    </TreeViewItem> 
</ControlTemplate> 

Entrambi i parametri ItemViewModel.IsGroupExpanded setter e getter reindirizzano a Group.IsExpanded.

Si noti che è necessario specificare Mode=TwoWay, poiché sembra legato OneWay per impostazione predefinita.

Problemi correlati