2010-01-13 18 views

risposta

3

Questo non è supportato in DataGrid nel toolkit e sembra che sia won't be supported quando DataGrid viene fornito con .NET 4. Ancora un altro motivo per cui questo controllo non è pronto per l'uso di produzione. Vorrei andare con una di queste opzioni:

  1. rotolare il proprio griglia con ListView/GridView
  2. modificare il codice sorgente del DataGrid nel toolkit (che non dovrebbe essere troppo difficile in quanto la selezione estesa è già supportato ?)
  3. cercare qualsiasi delle DataGrid commerciali WPF disponibili (in genere aggiungono quantità enorme di funzionalità utili)

sono d'accordo che il DataGrid dovrebbe sostenere questo e penso che si dovrebbe file a bug/suggestion per questo comunque. Forse non è troppo tardi per entrare in .NET 4 .. :)

3

Si può provare questa semplice soluzione, senza dover modificare/ereditare DataGrid controllo gestendo anteprima mouse evento come segue:

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

Il metodo TryFindFromPoint, da un blog post by Philipp Sumi, viene utilizzato per ottenere l'istanza DataGridRow dal punto su cui si è fatto clic.

Controllando ModifierKeys, è ancora possibile mantenere Ctrl e Shift come comportamento predefinito.

Solo un modo per tornare indietro da questo metodo è che non è possibile fare clic e trascinare per eseguire la selezione dell'intervallo come può in origine.

10

Stavo creando un'applicazione con un requisito simile che avrebbe funzionato sia per il touchscreen che per il desktop. Dopo aver trascorso un po 'di tempo, la soluzione che ho trovato sembra più pulita. Nella finestra di progettazione, ho aggiunto le seguenti setter di eventi per il datagrid:

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

Poi nel codebehind, ho gestito gli eventi come:

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

Ecco il codice per il metodo di supporto 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; 
} 

Speranza che aiuta qualcun altro troppo.

0

Sulla base di un precedente articolo, ho scritto un ("come") Codice MVVM:

In primo luogo aggiungere questo alla tua vista principale:

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

La parte rilevante di Vista:

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

Maggiori informazioni su EventToCommandBehavior: here

In questo modo, il vostro ViewModel devono attuare questi comandi:

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

Infine implementare un metodo (da qualche parte in Model) per trovare la riga (s).

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

Questa soluzione funziona perfettamente per me quindi spero che possa essere d'aiuto anche per voi.