2011-12-05 13 views
8

Po przejściu do WPF Datagrid ogniskuje pierwszą komórkę (z prostokąta), ale nie wybiera go (na niebiesko). Jeśli ponownie naciśniesz kartę, ostrość zostanie ustawiona na i.W jaki sposób uczynić WPF Datagrid wybrać komórkę, gdy pierwszy raz go w nim tabulatora?

Myślę, że DataGridCell rzeczywiście ma IsSelected = true, ale nie jest pomalowany na niebiesko. Próbowałem hakować z datagridem i wizualnymi stacjami, ale nie mogę sprawić, by odświeżyły poprawnie siatkę, gdy pierwszy raz wejdziesz.

Czy ktoś to widział wcześniej i czy masz rozwiązanie?

kod do reprodukcji:

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; } 
    } 
} 

kliknij na pole tekstowe, a następnie naciśnij kartę --- komórka 1 nie wybrano

Ponownie kliknij kartę --- komórka 2 jest wybrana

Każda pomoc jest doceniana, dzięki.

Aktualizacja:

Kiedy SelectionUnit = FullRow, miałem pewne sukcesy wzdłuż linii przedstawionych poniżej, jeśli SelectedIndex jest ustawiony na 0 po utworzeniu pierwszy wiersz jest teraz wybrany na niebiesko. Nadal potrzebuje trochę pracy, aby poradzić sobie z kartą shift itp. Problem nadal istnieje, ponieważ po zmianie trybu Selection na opcję extended i naciśnięciu shift-downarrow wybierany jest drugi wiersz, ale pierwszy wiersz zostaje odznaczony (oba powinny być wybrane) . Jeśli zrobię to ponownie, wybiorą się wiersze 2 + 3, co jest poprawne i dalej działa po tym.

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

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

Dalsze Aktualizacja:

Poprawiono ten problem przez ustawienie pola prywatną _selectionAnchor. (Dzięki 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

Myślę, że musisz użyć hasfocus, ale nie pozytywny, więc nie publikuję jako odpowiedź. – Paparazzi

+0

Co ciekawe, otrzymuję 'StackOverflowException' podczas próby podsłuchiwania właściwości' DataGrid' podczas debugowania. –

Odpowiedz

4

Możesz to zrobić. Zarejestruj się, aby uzyskać fokus, a następnie ustaw oryginalne źródło jako wybrany element.

<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> 

Następnie w kodzie za akt:

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

    } 

Mam nadzieję, że to pomaga!

+0

Rzeczywiście zrezygnowałem z kontroli DataGrid i wróciłem do ListView, gdzie mam większą kontrolę nad tym rodzajem zachowania. Zaznaczam to jako odpowiedź, ponieważ brzmi dobrze i jest to jedyna, którą otrzymałem, dzięki GuruC! –

+0

Jeśli 'DataGrid.SelectionUnit' to' FullRow', to musisz użyć 'VisualTreeHelper' do przejścia wizualnego drzewa z' e.OriginalSource', który jest 'DataGridCell' do rodzica' DataGridRow'. Następnie musisz ustawić "IsSelected = true" w wierszu zamiast na komórce. Poza tym to rozwiązanie działa. –

3

Wiem, że moja odpowiedź jest za późna, ale pomogłaby innym nawigacjom na tej stronie.

Po wielu badaniach otrzymałem odpowiedź, w jaki sposób wybrać element podczas przechwytywania. To było naprawdę łatwe i stanowiło prostą linię kodu w XAML;

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

Ustawiając IsTabStop false mówisz drzewo wizualną datagridcell by wejść do środka swojego szablonu i znaleźć żadnego elementu, który jest w stanie skupić. Jeśli znajdzie jakiś element, to skupia ten element.

Powiązane problemy