2011-12-05 24 views
8

Al tabular en la cuadrícula de datos de WPF, enfoca la primera celda (con un rectángulo) pero no la selecciona (en azul). Si presiono tab otra vez, enfoca y lo selecciona.Cómo hacer que la cuadrícula de datos de WPF seleccione una celda cuando la tabula por primera vez

Creo que el DataGridCell en realidad tiene IsSelected = true, pero no está pintado en azul. He intentado hackear con la cuadrícula de datos y los estados visuales, pero no puedo hacer que vuelva a dibujar la cuadrícula correctamente la primera vez que pulsalo.

¿Alguien ha visto esto antes y tienes una solución?

código para reproducir:

MainWindow.xaml

<Window x:Class="WpfApplication1.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="MainWindow" Height="350" Width="525"> 
    <StackPanel> 
     <TextBox Width="100"/> 
     <DataGrid SelectionMode="Single" SelectionUnit="Cell" 
       ItemsSource="{Binding MyItems}" AutoGenerateColumns="True"/> 
    </StackPanel> 
</Window> 

MainWindow.xaml.cs

using System.Collections.Generic; 
using System.Windows; 

namespace WpfApplication1 
{ 
    public partial class MainWindow : Window 
    { 
     public MainWindow() 
     { 
      InitializeComponent(); 

      MyItems.Add(new Thingy() { Name = "Frank", Age = 34 }); 
      MyItems.Add(new Thingy() { Name = "Jim", Age = 43 }); 
      MyItems.Add(new Thingy() { Name = "Bob", Age = 56 }); 
      MyItems.Add(new Thingy() { Name = "Harry", Age = 23 }); 

      DataContext = this; 
     } 

     private List<Thingy> _myItems = new List<Thingy>(); 
     public List<Thingy> MyItems 
     { 
      get { return _myItems; } 
     } 
    } 

    public class Thingy 
    { 
     public string Name { get; set; } 
     public int Age { get; set; } 
    } 
} 

clic en el cuadro de texto y, a continuación pestaña golpear --- celda 1 no está seleccionada

pulse la pestaña nuevamente --- la celda 2 está seleccionada

Cualquier ayuda es muy apreciada, gracias.

Actualización:

Cuando SelectionUnit = FullRow, he tenido cierto éxito a lo largo de las líneas que se muestran a continuación, si SelectedIndex se establece en 0 durante la creación de la primera fila es ahora seleccionada en azul. Todavía necesita algo de trabajo para lidiar con shift-tab, etc. Todavía hay un problema porque cuando cambio el SelectionMode a extended y presiono shift-downarrow se selecciona la segunda fila pero la primera fila se deselecciona (ambos deben seleccionarse) . Si vuelvo a hacerlo, se seleccionan las filas 2 + 3, que son correctas y continúan funcionando bien después de eso.

protected override void OnIsKeyboardFocusWithinChanged(DependencyPropertyChangedEventArgs e) 
    { 
     base.OnIsKeyboardFocusWithinChanged(e); 

     int oldIdx = this.SelectedIndex; 
     this.SelectedIndex = -1; 
     this.SelectedIndex = oldIdx; 
    } 

nueva actualización:

fijo que problema estableciendo el campo _selectionAnchor privado. (Gracias ILSpy)

protected override void OnIsKeyboardFocusWithinChanged(DependencyPropertyChangedEventArgs e) 
    { 
     base.OnIsKeyboardFocusWithinChanged(e); 

     this.SelectedIndex = -1; 
     this.SelectedIndex = 0; 

     SelectionAnchor = SelectedCells[0]; 
    } 

    protected DataGridCellInfo? SelectionAnchor 
    { 
     get 
     { 
      return typeof(DataGrid).GetField("_selectionAnchor", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(this) as DataGridCellInfo?; 
     } 
     set 
     { 
      typeof(DataGrid).GetField("_selectionAnchor", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(this, value); 
     } 
    } 
+0

Creo que necesitas utilizar hasfocus pero no es positivo, así que no estoy publicando como respuesta. – Paparazzi

+0

Curiosamente, obtengo una 'StackOverflowException' al intentar husmear las propiedades de' DataGrid' durante la depuración. –

Respuesta

4

Puede hacerlo así. Regístrese para obtener un evento de enfoque y luego configure la fuente original como elemento seleccionado.

<Window x:Class="WpfApplication1.MainWindow" 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
Title="MainWindow" Height="350" Width="525"> 
<StackPanel> 
    <TextBox Width="100"/> 
    <DataGrid SelectionMode="Single" SelectionUnit="Cell" 
      ItemsSource="{Binding MyItems}" AutoGenerateColumns="True" 
      GotFocus="WPF_DataGrid_GotFocus" /> 
</StackPanel> 
</Window> 

Luego, en el código detrás de archivo:

private void WPF_DataGrid_GotFocus(object sender, RoutedEventArgs e) 
    { 
     (e.OriginalSource as DataGridCell).IsSelected = true; 

    } 

espero que ayude!

+0

De hecho, abandoné el control DataGrid y volví al ListView donde tengo más control sobre este tipo de comportamiento. Estoy marcando esto como la respuesta porque suena bien y es el único que tengo, ¡gracias GuruC! –

+0

Si 'DataGrid.SelectionUnit' es' FullRow', entonces tienes que usar 'VisualTreeHelper' para recorrer el árbol visual desde' e.OriginalSource' que es 'DataGridCell' al padre' DataGridRow'. Luego debe establecer 'IsSelected = true' en la fila en lugar de en la celda. Aparte de eso, esta solución funciona. –

3

Sé que mi respuesta es demasiado tarde, pero ayudaría a otros a navegar en este sitio.

Después de mucha investigación, obtuve la respuesta sobre cómo seleccionar el elemento al tabular. Fue realmente fácil y fue una sola línea de código en XAML lo que hizo el truco;

<Style TargetType="{x:Type DataGridCell}"> 
    <Setter Property="IsTabStop" Value="False"/> 
</Style> 

Al establecer IsTabStop a falso le están diciendo árbol visual de la DataGridCell a ir dentro de su plantilla y encontrar ningún elemento que es capaz de enfocar. Si encuentra algún elemento, entonces enfoca ese elemento.

Cuestiones relacionadas