2011-04-06 155 views
2

我有一个ListView控件,我想调整最后一列的大小,使其与Window的大小同步。因此,如果Window的宽度增加100个单位,我希望列的宽度也增加100.如何根据WPF中的窗口大小调整某个控件的大小?

我应该在窗口上使用Resize事件并使用幻数来手动调整列标题大小,有点像?:

columnHeader.Width = windowSize.X - 400; 

回答

1

我不能充分信贷这个答案,因为我得到了它here

但基本上是这样的想法:

更换“查看”与GridView的ListView控件。然后,您可以为第一列指定任何想要的宽度。在这种情况下100,50,50 然后,我们添加的最后一列,即作为输入父ListView控件的结合。但是,我们允许一个变换器做肮脏的工作,为我们的。

<ListView> 
    <ListView.View> 
     <GridView> 
     <GridViewColumn Header="Title" DisplayMemberBinding="{Binding}" Width="100"/> 
     <GridViewColumn Header="Title" DisplayMemberBinding="{Binding}" Width="50"/> 
     <GridViewColumn Header="Title" DisplayMemberBinding="{Binding}" Width="50"/> 
     <GridViewColumn Header="4" DisplayMemberBinding="{Binding}"> 
     <GridViewColumn.Width> 
      <MultiBinding Converter="{StaticResource starWidthConverter}"> 
      <Binding Path="ActualWidth" RelativeSource="{RelativeSource AncestorType=ListView}"/> 
      <Binding RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType=ListView}"/> 
      </MultiBinding> 
     </GridViewColumn.Width> 
     </GridViewColumn> 
    </GridView> 
    </ListView.View> 
    <ListViewItem>item1</ListViewItem> 
    <ListViewItem>item2</ListViewItem> 
    <ListViewItem>item3</ListViewItem> 
    <ListViewItem>item4</ListViewItem> 
    </ListView> 

所以,在转换器 '转换' 功能,我们这样做:

ListView listview = value[1] as ListView; 
double width = listview.ActualWidth; 
GridView gv = listview.View as GridView; 
for(int i = 0;i < gv.Columns.Count-1;i++) 
{ 
    if(!Double.IsNaN(gv.Columns[i].Width)) 
    width -= gv.Columns[i].Width; 
} 
return width - 5;// this is to take care of margin/padding 

哪个抓住ListView的宽度,并计算新的大小。

+0

顺便说一句我忘了问,但是当以编程方式设置列宽时,是否会像用户在手动调整对应单元格的大小时那样调整大小? – 2011-04-07 00:03:05

+0

好吧,我添加了这个,但它没有做任何事情,宽度看起来像它被设置为自动,但我添加了转换器和绑定,视图已经设置为gridviewcolumn像在Dave的帖子。 – 2011-04-07 00:20:36

+0

对不起,我做了一个糟糕的假设,我提供的链接中的代码实际上工作。现在它应该工作。 – Liz 2011-04-07 00:29:16

7

这是一个解决方案,使用数据绑定和一些转换器魔术来完成工作。

首先,让我们描述一个简单的带有一些数据和3列的ListView。

<ListView> 
    <ListView.View> 
     <GridView> 
      <GridViewColumn Width="140" Header="Date" /> 
      <GridViewColumn Width="140" Header="Day" 
          DisplayMemberBinding="{Binding DayOfWeek}" /> 
      <GridViewColumn Width="140" Header="Year" 
          DisplayMemberBinding="{Binding Year}"/> 
     </GridView> 
    </ListView.View> 

    <sys:DateTime>1/2/3</sys:DateTime> 
    <sys:DateTime>4/5/6</sys:DateTime> 
    <sys:DateTime>7/8/9</sys:DateTime> 
</ListView> 

这会让我们到你所在的位置。现在,为了让最后一列根据父宽度增长和缩小,我们需要建立一个转换器并将其挂接。首先,我们调整GridView的最后一列以使宽度变为动态。

<GridViewColumn Header="Year" DisplayMemberBinding="{Binding Year}"> 
    <GridViewColumn.Width> 
     <MultiBinding Converter="{StaticResource lastColumnMaximizerConverter}"> 
      <Binding Path="ActualWidth" 
        RelativeSource="{RelativeSource AncestorType=ListView}"/> 
      <Binding Path="View.Columns" 
        RelativeSource="{RelativeSource AncestorType=ListView}"/> 
     </MultiBinding> 
    </GridViewColumn.Width> 
</GridViewColumn> 

我们在这里做的是创造了一个MultiBinding对象,迷上了一个IMultiValueConverter,并描述了我们要发送到IMultiValueConverter实现几个参数。第一个参数是父级ListView的ActualWidth。第二个参数是父级ListView上的View.Columns集合。我们现在拥有了我们需要的一切来计算我们视图中最后一列的最终宽度。

现在我们需要创建一个IMultiValueConverter实现。我碰巧在这里有一个。

public class WidthCalculationMultiConverter : IMultiValueConverter 
{ 
    public object Convert(object[] values, Type targetType, 
          object parameter, CultureInfo culture) 
    { 
     // do some sort of calculation 
     double totalWindowWidth; 
     double otherColumnsTotalWidth = 0; 
     double.TryParse(values[0].ToString(), out totalWindowWidth); 
     var arrayOfColumns = values[1] as IList<GridViewColumn>; 

     for (int i = 0; i < arrayOfColumns.Count - 1; i++) 
     { 
      otherColumnsTotalWidth += arrayOfColumns[i].Width; 
     } 

     return (totalWindowWidth - otherColumnsTotalWidth) < 0 ? 
        0 : (totalWindowWidth - otherColumnsTotalWidth); 
    } 

    public object[] ConvertBack(object value, Type[] targetTypes, 
           object parameter, CultureInfo culture) 
    { 
     throw new NotImplementedException(); 
    } 
} 

Psst ..顺便说一句,这不是最安全的代码。你会想要修剪它!这只是一个演示,你知道如何演示代码! :)

最后,我们需要在我们的XAML中实例化我们的Converter实例。

<Grid.Resources> 
    <Converters:WidthCalculationMultiConverter 
        x:Key="lastColumnMaximizerConverter"/> 
</Grid.Resources> 

所以现在我们有AA转换器,它会找出我们想要多宽,使最后一列的基础上,列在ListView的宽度(不包括最后一个)和绑定将使用该转换器并发送所需参数并获得“正确答案”并将其应用到最后一列的宽度。

如果你把这个共同的权利,你现在应该有一个ListView中的最后一列会一直延伸到父ListView中的最大宽度。

我希望这可以让你去,但也帮助你理解我们如何做到这一点,而无需编写一些代码隐藏和使用WPF提供的更多设施。

+0

顺便说一句我忘了问,但是当以编程方式设置列宽时,它是否会像用户在相应的单元格被调整大小时手动调整它的大小? – 2011-04-07 00:02:45

+0

我不知道我是否理解您的问题,但是如果您调整列的大小,那么该列中的所有单元格将与列宽相匹配。您不必调整所有单元格的大小。 – 2011-04-07 05:52:30

+0

谢谢,这正是我所问的。我问这个问题的原因是因为当你隐藏一个columnheader时,它并没有隐藏单元格,所以我认为缩放也适用于columnheader。 – 2011-04-07 16:37:21