如何使ListView不可选,宽度如“*”,并使用DataTemplate

时间:2014-10-24 09:23:10

标签: wpf xaml listview

我正在学习使用ListView列出包含多列的数据(例如,第1列是文件名,第2列是页数等),并遇到了几个问题:

  1. 下面的代码显示了2列,其中列宽由<GridViewColumn Width="Auto">指定。如何指定要使用所有可用宽度的列?我尝试将Width="*"设置为Grid的{​​{1}},但这会产生错误。

  2. 如何使ListView不可选?我看到this post使ListBox无法选择,但类似的方法对ListView无效(在代码中显示)。

  3. 更新:解决了问题#2。见代码。

    1. 您能否使用ListView显示DataTemplate的简单示例?我只想在MainWindow中找到类似<ListView ItemsSource="{Binding }" ItemTemplate="{StaticResource myTemplate}"/>的内容,以便保持清洁。
    2. (4.ish。我从this post学到了以下代码。如果有更简单的方法,请告诉我。)

      谢谢!

      <ListView HorizontalContentAlignment="Stretch" Grid.Row="0" ItemsSource="{Binding }">
      
          <ListView.ItemContainerStyle>
              <Style TargetType="ListViewItem">
                  <Setter Property="Focusable" Value="False"/>   <--- disable selection
              </Style>
          </ListView.ItemContainerStyle>
      
          <ListView.View>
              <GridView>
                  <GridViewColumn Width="Auto">
                      <GridViewColumnHeader Content="Filename"/>
                      <GridViewColumn.CellTemplate>
                          <DataTemplate>
                              <TextBlock Text="{Binding Path=Filename}"/>
                          </DataTemplate>
                      </GridViewColumn.CellTemplate>
                  </GridViewColumn>
      
                  <GridViewColumn Width="Auto">
                      <GridViewColumnHeader Content="Pages"/>
                      <GridViewColumn.CellTemplate>
                          <DataTemplate>
                              <TextBlock Text="{Binding Path=Pages}"/>
                          </DataTemplate>
                      </GridViewColumn.CellTemplate>
                  </GridViewColumn>
      
              </GridView>
          </ListView.View>
      <ListView>
      

1 个答案:

答案 0 :(得分:1)

我不确定是否还有其他直接的解决方案(虽然我几乎可以肯定没有任何直接的方法)。以下解决方案可以被视为解决方法,但它实际上是一个漂亮的解决方案。

您可以使用某些Binding将ListView的列宽度绑定到Grid的列宽度,从而使第二列(或通常是最后一列)填充剩余空间。是的,我们知道只有Grid具有其他控件没有的功能。以下是详细步骤:

  • 首先,我们需要Grid与ListView具有相同数量的列。 ListView当然应该放在这个Grid里面。通过使用Grid.ColumnSpan,我们可以使ListView填充整个网格。
  • 其次,将所有网格列的宽度绑定到相应ListView列 的实际宽度, 最后一列。网格的最后一列应将Width设置为*(填充剩余空间)。
  • 最后,您需要在网格的最后一列放置一些虚拟元素(例如边框)。我们需要这个虚拟元素来获取它的ActualWidth,这样我们就可以将最后一个ListView列的宽度绑定到ActualWidth。网格的ColumnDefinition还包含属性ActualWidth ,但 它不是依赖项属性 它也没有任何属性更改通知机制(所以我们不能使用该属性)。

现在是工作代码:

<Grid Grid.Row="0">
  <Grid.ColumnDefinitions>
    <ColumnDefinition Width="{Binding ActualWidth,ElementName=firstCol}"/>
    <ColumnDefinition Width="*"/>
  </Grid.ColumnDefinitions>
  <!-- the dummy element -->
  <Border Grid.Column="1" Name="dummy" Margin="5"></Border>
  <ListView HorizontalContentAlignment="Stretch" Grid.ColumnSpan="2"
          ItemsSource="{Binding }">

     <ListView.ItemContainerStyle>
        <Style TargetType="ListViewItem">
          <Setter Property="Focusable" Value="False"/>
        </Style>
     </ListView.ItemContainerStyle>

     <ListView.View>
        <GridView>
          <GridViewColumn Width="Auto" x:Name="firstCol">
              <GridViewColumnHeader Content="Filename"/>
              <GridViewColumn.CellTemplate>
                  <DataTemplate>
                    <TextBlock Text="{Binding Path=Filename}"/>
                  </DataTemplate>
              </GridViewColumn.CellTemplate>
           </GridViewColumn>

           <GridViewColumn Width="{Binding ActualWidth, ElementName=dummy}">
              <GridViewColumnHeader Content="Pages"/>
              <GridViewColumn.CellTemplate>
                  <DataTemplate>
                    <TextBlock Text="{Binding Path=Pages}"/>
                  </DataTemplate>
              </GridViewColumn.CellTemplate>
           </GridViewColumn>

        </GridView>
      </ListView.View>
  <ListView>
</Grid>

请注意,原始ListView可能会放置在某个网格中(您设置其Grid.Row="0")。但是,在使用此技巧时,ListView应始终放在包装器Grid 中,您必须为此包装器设置Grid.Row="0"(尽管这是默认设置)Grid 1}}而不是。我的意思是这个包装器网格将被放置在你原来的Grid中(如果有的话)。

更新:为了使其像Grid一样动态,您需要更多虚拟元素(我们在上面的代码中仅使用1个虚拟边框作为最后一列)。每个虚拟元素都将放在每个Grid的列中。正如我解释的那样,我们需要这个来代理Grid的列的ActualWidth,尽管ColumnDefinition也有ActualWidth属性但它不能在Binding中使用(不支持任何更改通知)。这是代码:

<Grid Grid.Row="0">
  <Grid.ColumnDefinitions>
    <ColumnDefinition Width="*"/>
    <ColumnDefinition Width="2*"/>
  </Grid.ColumnDefinitions>
  <!-- the dummy elements -->
  <Border Grid.Column="0" Name="dummy1" Margin="5"></Border>
  <Border Grid.Column="1" Name="dummy2" Margin="5"></Border>
  <!-- your ListView -->
  <ListView HorizontalContentAlignment="Stretch" Grid.ColumnSpan="2"
          ItemsSource="{Binding }">

     <ListView.ItemContainerStyle>
        <Style TargetType="ListViewItem">
          <Setter Property="Focusable" Value="False"/>
        </Style>
     </ListView.ItemContainerStyle>

     <ListView.View>
        <GridView>
          <GridViewColumn Width="{Binding ActualWidth, ElementName=dummy1}">
              <GridViewColumnHeader Content="Filename"/>
              <GridViewColumn.CellTemplate>
                  <DataTemplate>
                    <TextBlock Text="{Binding Path=Filename}"/>
                  </DataTemplate>
              </GridViewColumn.CellTemplate>
           </GridViewColumn>

           <GridViewColumn Width="{Binding ActualWidth, ElementName=dummy2}">
              <GridViewColumnHeader Content="Pages"/>
              <GridViewColumn.CellTemplate>
                  <DataTemplate>
                    <TextBlock Text="{Binding Path=Pages}"/>
                  </DataTemplate>
              </GridViewColumn.CellTemplate>
           </GridViewColumn>

        </GridView>
      </ListView.View>
  <ListView>
</Grid>