2009-08-29 21 views
10

我在XAML中有一個WPF ListView/GridView spec'd。第一列使用CellTemplate來指定圖標,其他使用DisplayMemberBinding來填充它們自己。圖標列是20寬,圖標16,但他們被邊緣/填充/東西截斷。我無法確定它的設置。在wpf ListView GridView上邊距/填充位置在哪裏?

這裏的要領(我已經刪除了一些列,因爲它們是相同的):

<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只是原來的對象類型爲圖像,以每種類型的項目得到它自己的圖標。

回答

6

使用Snoop來確定哪個元素負責施加額外間距。將鼠標懸停在空間上並按住並移動。該元素將在視覺樹中突出顯示。

+0

不錯,謝謝。 – serialhobbyist 2009-09-03 14:49:40

8

默認情況下,每個單元格的硬編碼邊距爲6,0。可能這是你的問題。您可以通過在單元格模板中設置-6,0的邊距來覆蓋此行爲

37

GridView的許多功能都被硬編碼到類中。特別是GridViewRowPresenter爲每個單元格創建一個硬編碼的TextBlock或ContentPresenter容器,並且無論您是否喜歡,都會將邊距強制爲6,0,6,0。

通常情況下,我會勸阻你從事任何涉及硬編碼負餘量的補償,因爲這是一種黑客攻擊。但是,在拆分GridViewRowPresenter之後,沒有其他選項。

我的第一次嘗試是重寫在GridViewRowPresenter類中創建的容器控件的隱式樣式,但該控件是沒有可覆蓋模板的TextBox或ContentPresenter。

我的第二次嘗試是反彙編代碼並構建一個新的GridViewRowPresenter。恐怕在課堂上有太多亂倫的「內部」要求讓這個解決方案成爲可行的解決方案。

一個更聰明的架構師會提供一個DependencyProperty,它允許類的用戶覆蓋爲每個單元創建的容器。出於某種原因,他們允許使用標題而不是實際的單元格內容。

因此,我們留下的事實是,GridRowPresenter中的單元格既不能被覆蓋,反向工程,也不能模板化。我很抱歉,但是這個班的負面利潤率是最好的。

我們需要一個更好的ListView:儘管我欣賞他們原創的架構師試圖通過從演示文稿中離開ItemsPresenter來完成的任務,但GridView並不適合一個無目的界面。

0

我開發了一個基於Ian Griffiths的破解(http://www.interact-sw.co.uk/iangblog/2007/05/30/wpf-listview-column-margins)的解決方案。 控制執行以下操作:對的TextBlock或ContentPresenter通過GridViewRowPresenter創建該控制的填充依賴屬性

  • 套硬編碼保證金
  • 傳播這種控制的的Horizo​​ntalAlignment和VerticalAlignment到其容器
  • 復位保證金/填充用於ListViewItem/GridViewRowPresenter容器。

因此它給你一種硬編碼值的控制。

代碼:在XAML

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); } 
     } 
    } 

} 

示例用法(內側GridViewColumn的定義):

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

由於餘量是硬編碼的常數,唯一的解決辦法是使用的Reflexion通過改變它手。

在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 

它工作正常,在我的項目。