2010-01-13 16 views

Odpowiedz

3

Nie jest to obsługiwane w DataGrid w zestawie narzędzi i wygląda na to, że won't be supported, gdy DataGrid jest dostarczana z .NET 4 albo. Kolejny powód, dla którego ta kontrola nie jest gotowa do użycia w produkcji. Chciałbym przejść z jednej z tych opcji:

  1. przewróceniu własne siatki z ListView/GridView
  2. Modyfikacja kodu źródłowego DataGrid w zestawie narzędzi (to nie powinno być zbyt trudne, ponieważ rozszerzony wybór jest już obsługiwany ?)
  3. Look dla żadnego z komercyjnych datagrids WPF dostępny (na ogół dodać ogromną ilość użytecznych funkcjonalności)

Zgadzam się, że DataGrid powinien wspierać to i myślę, że powinien file a bug/suggestion za to w każdym razie. Może to nie jest zbyt późno, aby dostać go w .NET 4 .. :)

3

Można spróbować to proste obejście bez konieczności modyfikowania/dziedziczenie DataGrid kontroli przez obsługę podglądu myszką w dół zdarzenie następująco:

TheDataGrid.PreviewMouseLeftButtonDown += 
       new MouseButtonEventHandler(TheDataGrid_PreviewMouseLeftButtonDown); 


void TheDataGrid_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) 
{ 
    // get the DataGridRow at the clicked point 
    var o = TryFindFromPoint<DataGridRow>(TheDataGrid, e.GetPosition(TheDataGrid)); 
    // only handle this when Ctrl or Shift not pressed 
    ModifierKeys mods = Keyboard.PrimaryDevice.Modifiers; 
    if (o != null && ((int)(mods & ModifierKeys.Control) == 0 && 
               (int)(mods & ModifierKeys.Shift) == 0)) 
    { 
     o.IsSelected = !o.IsSelected; 
     e.Handled = true; 
    } 
} 

public static T TryFindFromPoint<T>(UIElement reference, Point point) 
       where T:DependencyObject 
{ 
    DependencyObject element = reference.InputHitTest(point) as DependencyObject; 
    if (element == null) 
     return null; 
    else if (element is T) 
     return (T)element; 
    else return TryFindParent<T>(element); 
} 

Metoda TryFindFromPoint z blog post by Philipp Sumi służy do pobrania instancji DataGridRow z klikniętego punktu.

Sprawdzając ModifierKeys, możesz zachować Ctrl i Shift jako domyślne zachowanie.

Tylko jeden powrót z tej metody polega na tym, że nie można klikać i przeciągać, aby dokonać wyboru zakresu, tak jak to możliwe.

10

Tworzyłem aplikację o podobnym wymaganiu, która byłaby odpowiednia zarówno dla ekranu dotykowego, jak i pulpitu. Po spędzeniu trochę czasu nad rozwiązaniem, które wymyśliłem, wydaje się być czystsze. W projektancie, dodałem następujące ustawiające zdarzeń do DataGrid:

<DataGrid.RowStyle> 
    <Style TargetType="DataGridRow" > 
    <EventSetter Event="MouseEnter" Handler="MouseEnterHandler"></EventSetter> 
    <EventSetter Event="PreviewMouseDown" Handler="PreviewMouseDownHandler"></EventSetter> 
    </Style> 
</DataGrid.RowStyle> 

Następnie w kodzie, I obsługiwane wydarzenia jak:

private void PreviewMouseDownHandler(object sender, MouseButtonEventArgs e) 
{ 
    if (e.LeftButton == MouseButtonState.Pressed) 
    { 
     DataGridRow row = Utility.GetVisualParentByType(
        (FrameworkElement)e.OriginalSource, typeof(DataGridRow)) as DataGridRow; 

     row.IsSelected = !row.IsSelected; 
     e.Handled = true; 
    } 
} 

private void MouseEnterHandler(object sender, MouseEventArgs e) 
{ 
    if (e.OriginalSource is DataGridRow && e.LeftButton == MouseButtonState.Pressed) 
    { 
     DataGridRow row = e.OriginalSource as DataGridRow; 

     row.IsSelected = !row.IsSelected; 
     e.Handled = true; 
    } 
} 

Oto kod dla metody pomocnika GetVisualParentByType:

public static DependencyObject GetVisualParentByType(DependencyObject startObject, Type type) 
{ 
    DependencyObject parent = startObject; 
    while (parent != null) 
    { 
     if (type.IsInstanceOfType(parent)) 
      break; 
     else 
      parent = VisualTreeHelper.GetParent(parent); 
    } 

    return parent; 
} 

Mam nadzieję, że pomoże to komuś innemu.

0

Bazując na poprzednim artykule napisałem ("jak") kod MVVM:

Po pierwsze dodać do swojej głównej Widok:

xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" 

Istotna część Widok:

 <DataGrid 
       Style="{StaticResource DataGridStyle}" 
       ItemsSource="{Binding Results}" 
       SelectionUnit="FullRow" 
       SnapsToDevicePixels="True" 
       SelectionMode="Extended"> <!--You can change selection mode with converter. It will work (i tested it.)--> 
     <i:Interaction.Behaviors> 
         <utils:EventToCommandBehavior Command="{Binding TouchCommand}" 
                Event="PreviewTouchDown" 
                PassArguments="True"></utils:EventToCommandBehavior> 
         <utils:EventToCommandBehavior Command="{Binding MouseCommand}" 
                Event="PreviewMouseDown" 
                PassArguments="True"></utils:EventToCommandBehavior> 
     </i:Interaction.Behaviors> 
     <DataGrid.Resources> 
      <Style TargetType="{x:Type DataGridRow}"> 
       <Setter Property="IsSelected"<Style.Triggers> 
        <Trigger Property="IsSelected" Value="True"> 
         <Setter Property="Background"> 
          <Setter.Value> 
           <SolidColorBrush> 
            <SolidColorBrush.Color> 
             <Color A="50" R="0" G="0" B="0" /> 
            </SolidColorBrush.Color> 
           </SolidColorBrush> 
          </Setter.Value> 
         </Setter> 
        </Trigger> 
       </Style.Triggers> 
      </Style> 
      </DataGrid.Resources> 
     <DataGrid.Columns> 
     <!-- your columns --> 
     </DataGrid.Columns> 
     </DataGrid> 

Więcej informacji o EventToCommandBehavior: here

W ten sposób Twój ViewModel musi wdrożyć te polecenia:

//i skipped the TouchCommand definition because MouseCommand runs for touch on screen too. 
    public RelayCommand<MouseButtonEventArgs> MouseCommand 
    { 
     get 
     { 
      return new RelayCommand<MouseButtonEventArgs>((e)=> { 
       if (e.LeftButton == MouseButtonState.Pressed) 
       { 
        //call this function from your utils/models 
        var row = FindTemplatedParentByVisualParent<DataGridRow>((FrameworkElement)e.OriginalSource,typeof(ICommandSource)); 
        //add ICommanSource to parameters. (if actual cell contains button instead of data.) Its optional. 
        if(row!=null) 
        { 
         row.IsSelected = !row.IsSelected; 
         e.Handled = true; 
        } 
       }     
      }); 
     } 
    } 

końcu wdrożyć metodę (gdzieś w Modelu), aby znaleźć wiersz (y).

public static T FindTemplatedParentByVisualParent<T>(FrameworkElement element,Type exceptionType = null) where T : class 
    { 
     if (element != null && (exceptionType == null || element.TemplatedParent == null || (exceptionType != null && element.TemplatedParent !=null && !exceptionType.IsAssignableFrom(element.TemplatedParent.GetType())))) 
     { 
      Type type = typeof(T); 
      if (type.IsInstanceOfType(element.TemplatedParent)) 
      { 
       return (element.TemplatedParent as T); 
      } 
      else 
      { 
       return FindTemplatedParentByVisualParent<T>((FrameworkElement)VisualTreeHelper.GetParent(element)); 
      } 
     } 
     else 
      return null; 
    } 

Rozwiązanie to działa na mnie idealnie więc mam nadzieję, że pomoże to dla ciebie też.