你的位置:首页 > ASP.net教程

[ASP.net教程]WPF ListView 选中问题


WPF ListView 选中问题

 摘自:http://www.cnblogs.com/BBHor/archive/2013/04/28/VisualTreeHelper-PreviewMouseDown.html

在项目中遇到了这样的问题,ListView通过数据绑定,有模板的情况下ListViewItem 里面的子控件点击之后默认是子控件获得焦点而不是Item获的焦点。

往往需要获取一个ListViewItem  而不是他的子控件,这时候应该怎么办呢?

先看前台XAML:

复制代码
 1 <ListView x:Name="lv_VMlist" 2              PreviewMouseDown="lv_VMlist_PreviewMouseDown" 3              SelectionChanged="lv_VMlist_SelectionChanged"> 4           <ListView.View> 5             <GridView> 6               <GridView.Columns> 7                 <GridViewColumn Width="100" 8                         DisplayMemberBinding="{Binding CallerID}" 9                         Header="主叫方号码" />10                 <GridViewColumn Width="110"11                         DisplayMemberBinding="{Binding Duration}"12                         Header="语音邮件长度" />13                 <GridViewColumn Width="70"14                         DisplayMemberBinding="{Binding External}"15                         Header="是否是外线" />16                 <GridViewColumn Width="80"17                         DisplayMemberBinding="{Binding Type,18                                        Converter={StaticResource etsc}}"19                         Header="类型" />20                 <GridViewColumn Width="70"21                         DisplayMemberBinding="{Binding AttachCount}"22                         Header="附件个数" />23                 <GridViewColumn Width="120"24                         DisplayMemberBinding="{Binding Time}"25                         Header="时间" />26                 <GridViewColumn Width="180" Header="操作">27                   <GridViewColumn.CellTemplate>28                     <HierarchicalDataTemplate>29                       <StackPanel Name="stackPanel" Orientation="Horizontal">30                         <Button Name="btnPlay"31                             Margin="0,0,5,0"32                             Command="{Binding RelativeSource={RelativeSource FindAncestor,33                                                     AncestorLevel=1,34                                                     AncestorType={x:Type ListView}},35                                      Path=DataContext.OnPlay}"36                             Content="播放"37                             Focusable="False" />38                         <Button Name="btnStop"39                             Margin="0,0,5,0"40                             Command="{Binding RelativeSource={RelativeSource FindAncestor,41                                                     AncestorLevel=1,42                                                     AncestorType={x:Type ListView}},43                                      Path=DataContext.OnStop}"44                             Content="停止" />45                         <Button Name="btnSaveAs"46                             Margin="0,0,5,0"47                             Click="btnSaveClick"48                             Content="另存为"49                             ToolTip="将语音邮件保存到本地" />50                         <Button Name="btnDel"51                             Margin="0,0,5,0"52                             Command="{Binding RelativeSource={RelativeSource FindAncestor,53                                                     AncestorLevel=1,54                                                     AncestorType={x:Type ListView}},55                                      Path=DataContext.OnDelete}"56                             Content="删除"57                             ToolTip="删除本条语音邮件" />58                         <Button Name="btnSendTo"59                             Margin="0,0,5,0"60                             Content="转发"61                             ToolTip="将本条语音邮件转发给他人" />62                       </StackPanel>63                     </HierarchicalDataTemplate>64                   </GridViewColumn.CellTemplate>65                 </GridViewColumn>66               </GridView.Columns>67             </GridView>68           </ListView.View>69         </ListView>
复制代码


要下手去寻找这时候得借助WPF里面的一个神奇的类:VisualTreeHelper  有了这个类几乎能得到界面的任何东西。当然了,先行条件是在子控件的事件触发之前就要出发一个事件去获取ListViewItem,此时我们想到一个事件就是PreviewMouseDown,因为他是鼠标事件,所以优先级比较高,当他触发了之后才会触发子控件的一些Click事件等

 

复制代码
 1  private void lv_VMlist_PreviewMouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e) 2     { 3       int index = -1; 4       DependencyObject depObj = e.OriginalSource as DependencyObject; 5 6       if (depObj == null) return; 7 8       do 9       {10         depObj = VisualTreeHelper.GetParent(depObj);11 12         //有可能是点击到listviewitem之外的东西,例如滚动条,这时候会为null13         if (depObj == null) break;14 15         //得到listviewitem16         if (depObj.GetType() == typeof(ListViewItem))17         {18           //再去获取父级,用来得到索引19           DependencyObject parent = VisualTreeHelper.GetParent(depObj);20 21           for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)22           {23             if (depObj == VisualTreeHelper.GetChild(parent, i))24             {25               //得到索引后马上跳出26               index = i;27               break;28             }29           }30           break;31         }32       }33       while (depObj != null);34 35       //证明已经找到36       if (index > -1)37       {38         lv_VMlist.SelectedIndex = index;39       }40     }
复制代码


 

但是需要注意的是,这样写思路倒是简单,就是数据量大的清空可能会影响效率,慎用!