有没有简单的方法使整行成为DataGrid的唯一可聚焦单元?

时间:2012-08-16 07:27:50

标签: wpf datagrid

我不需要在单元格之间进行焦点导航。 我尝试在单元格样式中设置Focusable =“False”并调整该行的focusvisualstyle,但在这种情况下选择失败。

2 个答案:

答案 0 :(得分:1)

是的,您需要将DataGrid的Selection Unit设置为FullRow,并将borderThickness to 0设置为FocusVisualStyle to null

<DataGrid SelectionUnit="FullRow">
  <DataGrid.CellStyle>
      <Style TargetType="DataGridCell">
          <Setter Property="BorderThickness" Value="0"/>
          <Setter Property="FocusVisualStyle" Value="{x:Null}"/>
       </Style>
  </DataGrid.CellStyle>
  <!-- ... -->
</DataGrid>

<强>更新

上面说的xaml最好只能用xaml方法做,但是如果你想要处理表格,那么你必须去后面的代码。这就是我实现它的方式 -

<DataGrid x:Name="dg" ItemsSource="{Binding Objects}" SelectionUnit="FullRow">
  <DataGrid.CellStyle>
     <Style TargetType="DataGridCell">
        <Setter Property="BorderThickness" Value="0"/>
        <Setter Property="FocusVisualStyle" Value="{x:Null}"/>
        <EventSetter Event="PreviewKeyDown" Handler="dg_PreviewKeyDown"/>
      </Style>
  </DataGrid.CellStyle>
</DataGrid>

背后的代码(我在这里做的是如果用户按下右键或左键只需处理它们  以便停止从一个单元格导航到另一个单元格,以防万一用户按Tab键,焦点  应该转到下一行(如果可用)而不是移动到下一个单元格 -

private void dg_PreviewKeyDown(object sender, KeyEventArgs e)
{
  if (e.Key == Key.Left || e.Key == Key.Right)
     e.Handled = true;
  else if (e.Key == Key.Tab)
  {
     DataGridRow a = UtilityFunctions.FindParent<DataGridRow>(sender as DependencyObject);
     DataGridRow nextDataGridRow =(DataGridRow)dg.ItemContainerGenerator
                                     .ContainerFromIndex(a.GetIndex() + 1);
     if (nextDataGridRow != null)
     {
        dg.SelectedIndex = a.GetIndex() + 1;
        DataGridCell cell = UtilityFunctions.FindChild<DataGridCell>
                              (nextDataGridRow as DependencyObject, "");
        cell.Focus();
     }
     e.Handled = true;
   }
}

在上面的代码中,我使用了一些实用程序函数来移动Visual树以在Visual树中查找必要的父或子。供您参考,代码如下 -

public class UtilityFunctions
{
   public static Parent FindParent<Parent>(DependencyObject child)
            where Parent : DependencyObject
        {
            DependencyObject parentObject = child;

            //We are not dealing with Visual, so either we need to fnd parent or
            //get Visual to get parent from Parent Heirarchy.
            while (!((parentObject is System.Windows.Media.Visual) || (parentObject is System.Windows.Media.Media3D.Visual3D)))
            {
                if (parentObject is Parent || parentObject == null)
                {
                    return parentObject as Parent;
                }
                else
                {
                    parentObject = (parentObject as FrameworkContentElement).Parent;
                }
            }

            //We have not found parent yet , and we have now visual to work with.
            parentObject = VisualTreeHelper.GetParent(parentObject);

            //check if the parent matches the type we're looking for
            if (parentObject is Parent || parentObject == null)
            {
                return parentObject as Parent;
            }
            else
            {
                //use recursion to proceed with next level
                return FindParent<Parent>(parentObject);
            }
        }

   public static T FindChild<T>(DependencyObject parent, string childName)
           where T : DependencyObject
        {
            // Confirm parent is valid.  
            if (parent == null) return null;

            T foundChild = null;

            int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
            for (int i = 0; i < childrenCount; i++)
            {
                var child = VisualTreeHelper.GetChild(parent, i);
                // If the child is not of the request child type child 
                T childType = child as T;
                if (childType == null)
                {
                    // recursively drill down the tree 
                    foundChild = FindChild<T>(child, childName);

                    // If the child is found, break so we do not overwrite the found child.  
                    if (foundChild != null) break;
                }
                else if (!string.IsNullOrEmpty(childName))
                {
                    var frameworkElement = child as FrameworkElement;
                    // If the child's name is set for search 
                    if (frameworkElement != null && frameworkElement.Name == childName)
                    {
                        // if the child's name is of the request name 
                        foundChild = (T)child;
                        break;
                    }
                }
                else
                {
                    // child element found. 
                    foundChild = (T)child;
                    break;
                }
            }

            return foundChild;
        }
}

答案 1 :(得分:0)

删除单元格之间的焦点导航:使用下面的代码