2009-08-29 8 views
10

Ho una WPF ListView/GridView spec'd in XAML. La prima colonna utilizza un oggetto CellTemplate per specificare le icone e gli altri utilizzano DisplayMemberBinding per popolare. La colonna delle icone è larga 20, le icone 16 ma vengono troncate dai margini/padding/qualcosa. Non riesco a capire dove è impostato.Dove sono i margini/riempimento impostato su un wpf ListView GridView?

Ecco gli elementi essenziali (ho rimosso alcune colonne perché sono la stessa cosa):

<ListView.ItemContainerStyle> 
    <Style TargetType="{x:Type ListViewItem}"> 
     <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" /> 
     <Setter Property="FontWeight" Value="Normal" /> 
     <Style.Triggers> 
      <Trigger Property="IsSelected" Value="True"> 
       <Setter Property="FontWeight" Value="Bold" /> 
      </Trigger> 
     </Style.Triggers> 
    </Style> 
</ListView.ItemContainerStyle> 

<ListView.Resources> 
    <DataTemplate x:Key="image"> 
     <Image Width="16" Height="16" Margin="0,0,0,0" 
          HorizontalAlignment="Center" 
          Source="{Binding Path=ObjectType, 
              Converter={StaticResource imageConverter} }" /> 
    </DataTemplate> 
</ListView.Resources> 

<ListView.View> 
    <GridView> 
     <GridViewColumn Width="20" 
         CellTemplate="{StaticResource image}"/> 
     <GridViewColumn Width="120" Header="Name" 
         DisplayMemberBinding="{Binding Path=Name}"/> 
    </GridView> 
</ListView.View> 

ImageConverter solo trasforma un ObjectType in un'immagine così ogni tipo di elemento ottiene la propria icona.

risposta

6

Utilizzare Snoop per determinare quale elemento è responsabile dell'impostazione della spaziatura aggiuntiva. Passa il mouse sopra lo spazio e tieni premuto il controllo e sposta. L'elemento verrà quindi evidenziato nell'albero visivo.

+0

Bello, grazie. – serialhobbyist

8

per impostazione predefinita, ogni cella ha un margine hardcoded di 6,0. Probabilmente è il tuo problema. È possibile sovrascrivere questo comportamento impostando un margine di -6,0 nel proprio numero di cella

37

Molte funzioni di GridView sono codificate nella classe. In particolare, GridViewRowPresenter crea un contenitore TextBlock o ContentPresenter con hard-coded per ciascuna cella e impone i margini a 6,0,6,0, che ti piaccia o no.

Normalmente vorrei scoraggiarvi da tutto ciò che comporta l'hard-coding di un margine negativo da compensare in quanto è un hack stratificato su un altro hack. Tuttavia, dopo aver smontato GridViewRowPresenter, non ci sono altre opzioni.

Il mio primo tentativo è stato quello di sovrascrivere lo stile implicito per il controllo contenitore che è stato creato nella classe GridViewRowPresenter, ma tale controllo è un TextBox o un ContentPresenter che non ha template da sovrascrivere.

Il mio secondo tentativo è stato quello di smontare il codice e creare un nuovo GridViewRowPresenter. Temo che ci siano troppe chiamate "interne" incestuose nella classe per rendere questa una soluzione praticabile.

Un architetto più intelligente avrebbe fornito una proprietà Dependency che consentiva all'utente della classe di sovrascrivere il contenitore creato per ogni cella. Per qualche motivo hanno permesso questo con le intestazioni ma non il contenuto effettivo della cella.

Quindi, rimane il fatto che le celle in un GridRowPresenter non possono essere sovrascritte, decodificate o non modificate. Mi dispiace, ma i margini negativi sono i migliori che si possono fare con questa classe.

Abbiamo bisogno di un ListView migliore: il GridView non è adatto per un'interfaccia senza look, anche se apprezzo ciò che gli architetti originali stavano cercando di fare dividendo l'ItemPresenter dalla presentazione.

0

Ho sviluppato una soluzione basata sull'hack di Ian Griffiths (http://www.interact-sw.co.uk/iangblog/2007/05/30/wpf-listview-column-margins). Il controllo esegue le seguenti operazioni:

  • insiemi Margine hard-coded per TextBlock o ContentPresenter creato da GridViewRowPresenter alla proprietà Padding dipendenze di questo controllo
  • propaga HorizontalAlignment di questo controllo e VerticalAlignment ai suoi contenitori
  • azzera Margine/Padding per contenitori ListViewItem/GridViewRowPresenter.

Quindi ti dà un tipo di controllo dei valori che sono hardcoded.

Codice: Utilizzo

using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Media; 

namespace Put.Your.Namespace.Here 
{ 
    /// <summary> 
    /// Class allows for reseting hard coded ListViewItem margins and paddings 
    /// </summary> 
    public class ListViewCustomizableCellPresenter : Decorator 
    { 
     protected override void OnVisualParentChanged(DependencyObject oldParent) 
     { 
     base.OnVisualParentChanged(oldParent); 

     var cp = VisualTreeHelper.GetParent(this) as FrameworkElement; 
     if (cp != null) 
     { 
      cp.Margin = Padding; 
      cp.VerticalAlignment = VerticalAlignment; 
      cp.HorizontalAlignment = HorizontalAlignment; 
     } 

     ResetGridViewRowPresenterMargin(); 
     ResetListViewItemPadding(); 
     } 

     private T FindInVisualTreeUp<T>() where T : class 
     { 
     DependencyObject result = this; 
     do 
     { 
      result = VisualTreeHelper.GetParent(result); 
     } 
     while (result != null && !(result is T)); 
     return result as T; 
     } 

     private void ResetGridViewRowPresenterMargin() 
     { 
     var gvrp = FindInVisualTreeUp<GridViewRowPresenter>(); 
     if (gvrp != null) 
      gvrp.Margin = new Thickness(0); 
     } 

     private void ResetListViewItemPadding() 
     { 
     var lvi = FindInVisualTreeUp<ListViewItem>(); 
     if (lvi != null) 
      lvi.Padding = new Thickness(0); 
     } 

     /// <summary> 
     /// Padding dependency property registration 
     /// </summary> 
     public static readonly DependencyProperty PaddingProperty = 
     DependencyProperty.Register("Padding", typeof(Thickness), typeof(ListViewCustomizableCellPresenter), new PropertyMetadata(default(Thickness))); 

     /// <summary> 
     /// Padding dependency property 
     /// </summary> 
     public Thickness Padding 
     { 
     get { return (Thickness)GetValue(PaddingProperty); } 
     set { SetValue(PaddingProperty, value); } 
     } 
    } 

} 

esempio in XAML (all'interno definizione di GridViewColumn):

<GridViewColumn.CellTemplate> 
    <DataTemplate> 
     <yourxamlnamespacehere:ListViewCustomizableCellPresenter Padding="0" 
                 VerticalAlignment="Center"> 
      <YourControlOrPanelHere /> 
     </yourxamlnamespacehere:ListViewCustomizableCellPresenter> 
    </DataTemplate> 
</GridViewColumn.CellTemplate> 
1

Poiché il margine è un disco codificato costante, unica soluzione è quella di utilizzare Riflessione di modifica facendo mano.

In VB:

' Hack : 
    ' Changes the default margin for the GridView's Column. 
    Dim GridViewCellMarginProperty = GetType(GridViewRowPresenter).GetField("_defalutCellMargin", BindingFlags.NonPublic Or BindingFlags.Static Or BindingFlags.GetField) 
    If (GridViewCellMarginProperty IsNot Nothing) Then 
     GridViewCellMarginProperty.SetValue(Nothing, New Thickness(2, 0, 2, 0)) 
    End If 

Funziona benissimo sul mio progetto.