2010-07-20 67 views
1

我有一個ListView。當我選擇一行時,我希望只選擇一個單元格而不是整行。我怎樣才能得到這個? 這是我的風格和模板。WPF ListView列選擇

<ListView x:Name="List"     
       ItemsSource="{Binding }" 
       ItemContainerStyle="{DynamicResource ListItemStyle}">   
     <ListView.View> 
      <GridView AllowsColumnReorder="False"> 
       <GridViewColumn HeaderContainerStyle="{StaticResource myHeaderStyle}"         
           Header="1" 
           CellTemplate="{StaticResource myCellTemplate1}">       
       </GridViewColumn> 

       <GridViewColumn Header="2"        
           HeaderContainerStyle="{StaticResource myHeaderStyle}" 
           HeaderTemplate="{StaticResource myHeaderTemplate}" 
           CellTemplate="{StaticResource cellTemplate2}">      
       </GridViewColumn> 

       <GridViewColumn Header="3" 
           HeaderContainerStyle="{StaticResource myHeaderStyle}" 
           HeaderTemplate="{StaticResource myHeaderTemplate}" 
           CellTemplate="{StaticResource cellTemplate3}" /> 

       <GridViewColumn Header="4" 
           HeaderContainerStyle="{StaticResource myHeaderStyle}" 
           HeaderTemplate="{StaticResource myHeaderTemplate}" 
           CellTemplate="{StaticResource cellTemplate4}"/> 

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

    <Style x:Key="ListItemStyle" TargetType="{x:Type ListViewItem}">    
    <Setter Property="Template"> 
     <Setter.Value> 
      <ControlTemplate TargetType="{x:Type ListViewItem}" > 
       <Grid SnapsToDevicePixels="True" Margin="0" Width="410" x:Name="GridSmall"> 
        <Border x:Name="Border"              
          Background="{TemplateBinding Background}" 
          BorderBrush="{TemplateBinding BorderBrush}" 
          BorderThickness="{TemplateBinding BorderThickness}" 
          CornerRadius="0" /> 
        <GridViewRowPresenter x:Name="Rows" /> 
       </Grid>      
      </ControlTemplate>     
     </Setter.Value> 
    </Setter> 
    <Style.Triggers>    
     <Trigger Property="IsSelected" Value="True"> 
      <Setter Property="Background" Value="Yellow"/> 
      <Setter Property="Foreground" Value="Black"/> 
     </Trigger> 
     <Trigger Property="IsSelected" Value="False"> 
      <Setter Property="Background" Value="Black"/> 
      <Setter Property="Foreground" Value="Green"/> 
     </Trigger> 
    </Style.Triggers> 
</Style> 

    <DataTemplate x:Key="myCellTemplate1"> 
    <DataTemplate.Resources> 
     <local:NullIdConverter x:Key="NullIdConverterKey"/>    
    </DataTemplate.Resources>   
    <DockPanel x:Name="RR"> 
     <TextBlock FontSize="18" x:Name="TxtBl"       
        HorizontalAlignment="Center"      
        Text="{Binding Path = Id}"/> 
    </DockPanel>  
</DataTemplate> 

謝謝。

回答

0

如果您使用的是.NET 3.5 SP1或.NET 4,我建議您查看DataGrid而不是ListView。

我認爲它爲您提供了更多的數據靈活性,並且有一個名爲SelectionUnit的屬性,您可以將其設置爲「單元」,從而爲您提供所需的功能。

不幸的是,我不認爲有一種簡單的方法可以對ListView執行相同的操作。

0

好.....這並不容易。像Scott說的那樣,在.Net 4及其DataGrid控件中使用SelectionUnit和SelectionMode可能會讓生活更加輕鬆。但是,如果你想這樣做,就像你開始嘗試這樣:

在XAML中(我沒有做整個事情作爲模板或樣式,只是一列來讓它工作),你需要代碼因爲這樣:

<GridViewColumn.CellTemplate> 
         <DataTemplate> 
          <Border Name="myOwnBorder" BorderBrush="Gray" BorderThickness="1,1,1,0" Margin="-6,0,-6,0"> 
           <Grid Margin="6,0,6,0"> 
            <TextBlock Text="{Binding}"/> 
           </Grid> 
          </Border> 
         </DataTemplate> 
        </GridViewColumn.CellTemplate> 

...然後在代碼behing(不是好的設計但對於演示的緣故)創建一個功能,如:

static bool FindBorderInListView(DependencyObject dep, ListView listView, 
      out Border border, out ListViewItem lvItem) 
     { 
      border = null; 
      lvItem = null; 

      DependencyObject depObj = dep; 
      while (depObj != listView) 
      { 
       if (border == null && depObj is Border) 
       { 
        border = depObj as Border; 
        if (border.Name != "myOwnBorder") 
        { 
         border = null; 
        } 
       } 
       else if (depObj is ListViewItem) 
       { 
        lvItem = depObj as ListViewItem; 
       } 

       depObj = VisualTreeHelper.GetParent(depObj); 
      } 
      return border != null && lvItem != null; 
     } 

,然後從它調用您的ListView的PreviewMouseDown事件:

private void MyList_PreviewMouseDown(object sender, MouseButtonEventArgs e) 
    { 
     Border border; 
     ListViewItem lvItem; 

     if (FindBorderInListView(e.OriginalSource as DependencyObject, this.MyList, 
      out border, out lvItem)) 
     { 

      ItemContainerGenerator generator = this.MyList.ItemContainerGenerator; 

      int rowIndex = generator.IndexFromContainer(lvItem); 
      int columnIndex = Grid.GetColumn(border); 

      MessageBox.Show("Cell #:" + rowIndex + columnIndex); 


     } 
    } 

信貸到期的信用,約什史密斯制定瞭如何在2007年左右做到這一點我認爲在回覆MSDN community question

祝你好運!我也必須在DataGrid中實現類似的東西。

+0

非常感謝您的回答,但問題在於:我使用鍵盤在列表中移動,但只高亮顯示了一行中的一個單元格。所以我不能使用PreviewMouseDown,因爲我根本不使用鼠標。可能嗎?或者我必須移動.NET4? – Void 2010-07-21 07:42:13