2010-05-27 14 views
23

Sto cercando di capire come far funzionare lo scroll del mouse su una finestra wpf con un scrollviewer e un datagrid al suo interno. Il WPF e codice C# è inferioreScorrimento del mouse non funzionante in un visualizzatore di scorrimento con un datagide wpf e elementi dell'interfaccia utente aggiuntivi

<ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto"> 
    <Grid> 
     <Grid.RowDefinitions> 
      <RowDefinition/> 
      <RowDefinition/> 
     </Grid.RowDefinitions> 
     <Grid Grid.Row="0"> 

      <Border Name="DataGridBorder" BorderThickness="2" Margin="1" CornerRadius="4" BorderBrush="#FF080757"> 
       <dg:DataGrid AutoGenerateColumns="False" Name="ValuesDataGrid" 
         BorderThickness="0" CanUserResizeColumns="True" FontWeight="Bold" HorizontalScrollBarVisibility="Auto" 
         CanUserReorderColumns="False" IsReadOnly="True" IsTextSearchEnabled="True" AlternationCount="2" 
         SelectionMode="Extended" GridLinesVisibility="All"     
         HeadersVisibility="Column" CanUserAddRows="False" CanUserDeleteRows="False" CanUserResizeRows="False" CanUserSortColumns="False" 
         RowDetailsVisibilityMode="Collapsed" SelectedIndex="0" 
         RowStyle="{StaticResource CognitiDataGridRowStyle}" 
         > 

        <dg:DataGrid.Columns> 
         <dg:DataGridTemplateColumn Header="Title" > 
          <dg:DataGridTemplateColumn.CellTemplate> 
           <DataTemplate> 
            <StackPanel Orientation="Horizontal" > 
             <TextBlock HorizontalAlignment="Left" VerticalAlignment="Center" Text="{Binding Path=Name}" FontWeight="Normal" /> 
            </StackPanel> 
           </DataTemplate> 
          </dg:DataGridTemplateColumn.CellTemplate> 
         </dg:DataGridTemplateColumn> 
        </dg:DataGrid.Columns> 
       </dg:DataGrid> 
      </Border> 
     </Grid> 
     <Button Grid.Row="1" Height="90" >hello world</Button> 
    </Grid> 
</ScrollViewer> 

e il codice C# è la seguente

public partial class Window1 : Window 
    { 
    public Window1() 
    { 
     InitializeComponent(); 
     initialize(); 
     } 

    public void initialize() 
    { 
     ObservableCollection<MyObject> testList = new ObservableCollection<MyObject>(); 

     for (int i = 0; i < 20; i++) 
     { 
      MyObject my = new MyObject("jack " + i); 
      testList.Add(my); 
     } 

     ValuesDataGrid.ItemsSource = testList; 



    } 
} 

public class MyObject 
{ 
    public string Name { get; set; } 



    public MyObject(string name) 
    { 
     Name = name; 
    } 
    } 

Il problema che sto affrontando è che quando si utilizza il mouse per scorrere, funziona benissimo quando è finita la pulsante ma non appena muovo il puntatore del mouse sulla griglia e provo a scorrere, non succede nulla. Sono in grado di spostare la barra di scorrimento dello scrollviewer direttamente però. Sono ancora un novizio wpf quindi qualsiasi aiuto su come far scorrere il mouse per lavorare sul datagrid sarebbe apprezzato. Immagino che ci dovrebbe essere una soluzione abbastanza semplice per questo, ma non sono stato in grado di capirlo

+0

Sto avendo esattamente lo stesso problema, tuttavia le soluzioni seguenti non funzionano molto bene in un'applicazione MVVM. Il nostro architetto non vuole alcun codice nelle viste, solo Xaml o Behaviors. – Kolky

+0

Ciao Kolky, so che questa risposta è probabilmente troppo tardi per te, quasi 6 anni, ma forse sarà utile per qualcun altro in una situazione simile. Normalmente, la logica del tipo di interfaccia utente come questa è accettabile utilizzando lo schema MVVM, come l'utilizzo del codice dietro la classe. Ecco un link a un articolo di MSDN su di esso: https://msdn.microsoft.com/en-us/library/gg405484(v=pandp.40).aspx –

risposta

11

Suppongo che DataGrid non abbia bisogno di scorrere: imposta VerticalScrollBar = "Nessuno" su DataGrid.

DataGrid inghiotte l'evento di scorrimento del mouse.

Quello che ho trovato è utilizzare l'evento PreviewMouseWheel per far scorrere il contenitore che si desidera scorrere. Sarà necessario nominare lo scrollviewer per modificare l'offset verticale.

private void DataGrid_PreviewMouseWheel(object sender, MouseWheelEventArgs e) 
    { 
     scrollViewer.ScrollToVerticalOffset(scrollViewer.VerticalOffset-e.Delta); 
    } 
51

Penso che la soluzione di Dave sia buona. Tuttavia, una raccomandazione che vorrei fare è catturare l'evento PreviewMouseWheel sul visualizzatore di scorrimento anziché sul datagrid. Se non lo fai, potresti notare alcune piccole differenze a seconda che tu stia scorrendo sul datagrid o sulla barra di scorrimento stessa. Il ragionamento è che lo scrollviewer gestirà lo scorrimento quando il mouse si posiziona sopra la barra di scorrimento e l'evento datagrid gestirà lo scorrimento quando si trova sul datagrid. Ad esempio, una rotellina del mouse che scorre sopra il datagrid potrebbe portarti più in basso nell'elenco, come farebbe quando ci si trova sulla barra di scorrimento. Se lo si cattura durante l'evento di anteprima scrollviewer, tutti useranno la stessa misura durante lo scorrimento. Inoltre, se la si cattura in questo modo, non sarà necessario denominare l'elemento scrollviewer, poiché non sarà necessario un riferimento all'oggetto poiché è possibile digitare semplicemente l'oggetto mittente passato nell'evento scrollviewer PreviewMouseWheel. Infine, consiglierei di contrassegnare l'evento gestito alla fine dell'evento, a meno che non sia necessario catturarlo in un elemento più in basso nell'eradarchia per qualche motivo. Esempio di seguito:

private void ScrollViewer_PreviewMouseWheel(object sender, MouseWheelEventArgs e) 
    { 
     ScrollViewer scv = (ScrollViewer)sender; 
     scv.ScrollToVerticalOffset(scv.VerticalOffset - e.Delta); 
     e.Handled = true; 
    } 
1

ho provato la soluzione di Don B ed è risolve il problema di scorrimento su una griglia di dati abbastanza bene per i casi in cui non si dispone di altri controlli scorrevoli interne.

Per il caso in cui il visualizzatore di scroll ha come altri controlli scorrevoli e una griglia di dati, quindi è necessario che l'evento non venga contrassegnato come gestito alla fine del gestore di eventi per il visualizzatore di scorrimento principale in modo che possa essere catturato anche nei controlli scorrevoli interni, tuttavia questo ha l'effetto collaterale che quando la pergamena si verifica solo sul controllo scrollabile interno, si verificherà anche sul visualizzatore di scorrimento principale.

Così ho aggiornato la soluzione di Dave con la differenza di come lo spettatore di scorrimento si trova in modo che non sarà necessario conoscere il nome dello spettatore di scorrimento:

private void DataGrid_PreviewMouseWheel(object sender, MouseWheelEventArgs e) 
{ 
    ScrollViewer scrollViewer = (((DependencyObject)sender).GetVisualParent<ScrollViewer>()); 
    scrollViewer.ScrollToVerticalOffset(scrollViewer.VerticalOffset - e.Delta); 
} 
+0

Sarebbe anche meglio, se non dipendesse da una libreria di terze parti. – linac

+1

Quale libreria di terze parti? Quelli sono controlli WPF nativi. –

+0

'GetVisualParent' no. – linac

0

Sono anche un WPF novizio e bloccato nello stesso identico problema

i.usando il mouse per scorrere, funziona bene quando si trova sopra il pulsante, ma non appena si sposta il puntatore del mouse sulla griglia e si prova a scorrere, non accade nulla.

Ma grazie a mio modo di lavorare cioè vado per un miglio in più e ho scoperto che ScrollViewer non può essere concatenato mezzi se è concatenato come nel tuo caso la griglia inizia sotto il tag ScrollViewer e nella Griglia abbiamo DataGrid e nel DataGrid di nuovo la proprietà ScrollViewer è stata impostata. cioè

HorizontalScrollBarVisibility="Auto".`      <Border Grid.Row="3" Name="contentArea" BorderBrush="Black" BorderThickness="1" Margin="10,0,10,10"> 
          <ScrollViewer CanContentScroll="True" IsDeferredScrollingEnabled="False" VerticalScrollBarVisibility="Auto"> 


           <Grid> 
            <Grid.RowDefinitions> 
             <RowDefinition Height="30"></RowDefinition> 
             <RowDefinition Height="45"></RowDefinition> 
             <RowDefinition Height="100*"></RowDefinition> 
             <RowDefinition Height="105"></RowDefinition>          
            </Grid.RowDefinitions> 
            <Grid.ColumnDefinitions> 
             <ColumnDefinition Width="*"></ColumnDefinition> 
             <ColumnDefinition Width="*"></ColumnDefinition> 

            </Grid.ColumnDefinitions> 


            <Label Grid.Row="0" Grid.Column="0" Margin="10,0,0,0" HorizontalAlignment="Left" VerticalAlignment="Center" FontWeight="Bold" Content="Vessel: " /> 
            <TextBox Height="30" Width="300" Margin="70,0,0,0" HorizontalAlignment="Left" BorderThickness="1,1,1,1" IsReadOnly="True" Name="txtVessel"/> 

            <Label Grid.Row="0" Grid.Column="2" Margin="0,0,185,0" HorizontalAlignment="Right" VerticalAlignment="Center" FontWeight="Bold" Content="Month:" /> 
            <StackPanel Orientation="Horizontal" Grid.Row="0" Grid.Column="2" Margin="0,0,0,0" HorizontalAlignment="Right" > 
             <ComboBox BorderThickness="2" HorizontalAlignment="Right" Name="CmbMonth" VerticalAlignment="Center" Width="90" /> 
             <ComboBox BorderThickness="2" HorizontalAlignment="Right" Margin="5,0,0,0" Name="CmbYear" VerticalAlignment="Center" Width="90" /> 
            </StackPanel> 
            <Grid Grid.Row="1" Grid.ColumnSpan="2"> 
             <Grid.RowDefinitions> 
              <RowDefinition Height="45"></RowDefinition> 
             </Grid.RowDefinitions> 
             <Grid.ColumnDefinitions> 
              <ColumnDefinition Width="30"></ColumnDefinition> 
              <ColumnDefinition Width="220"></ColumnDefinition> 
              <ColumnDefinition Width="80"></ColumnDefinition> 
              <ColumnDefinition Width="80"></ColumnDefinition> 
              <ColumnDefinition Width="80"></ColumnDefinition> 
              <ColumnDefinition Width="80"></ColumnDefinition> 
              <ColumnDefinition Width="120"></ColumnDefinition> 
              <ColumnDefinition Width="120"></ColumnDefinition> 
              <ColumnDefinition Width="140*"></ColumnDefinition> 
             </Grid.ColumnDefinitions> 

             <Border BorderBrush="Black" BorderThickness="0,1,1,1" Grid.Row="0" Grid.Column="0" ></Border> 
             <Border BorderBrush="Black" BorderThickness="0,1,1,1" Grid.Row="0" Grid.Column="1" ></Border> 
             <Border BorderBrush="Black" BorderThickness="0,1,1,1" Grid.Row="0" Grid.Column="2" ></Border> 
             <Border BorderBrush="Black" BorderThickness="0,1,1,1" Grid.Row="0" Grid.Column="3" ></Border> 
             <Border BorderBrush="Black" BorderThickness="0,1,1,1" Grid.Row="0" Grid.Column="4" ></Border> 
             <Border BorderBrush="Black" BorderThickness="0,1,1,1" Grid.Row="0" Grid.Column="5" ></Border> 
             <Border BorderBrush="Black" BorderThickness="0,1,1,1" Grid.Row="0" Grid.Column="6" ></Border> 
             <Border BorderBrush="Black" BorderThickness="0,1,1,1" Grid.Row="0" Grid.Column="7" ></Border> 
             <Border BorderBrush="Black" BorderThickness="0,1,1,1" Grid.Row="0" Grid.Column="8" ></Border> 
             <Label Grid.Row="0" Grid.Column="1" Margin="0,0,0,0" HorizontalAlignment="Center" VerticalAlignment="Center" FontWeight="Bold" Content="Item" /> 
             <Label Grid.Row="0" Grid.Column="2" Margin="0,0,0,0" HorizontalAlignment="Center" VerticalAlignment="Center" FontWeight="Bold" Content="Maker" /> 
             <Label Grid.Row="0" Grid.Column="3" Margin="0,0,0,0" HorizontalAlignment="Center" VerticalAlignment="Center" FontWeight="Bold" Content="Model" /> 
             <Label Grid.Row="0" Grid.Column="4" Margin="0,0,0,0" HorizontalAlignment="Center" VerticalAlignment="Center" FontWeight="Bold" Content=" Part No.&#x0a;Serial No." /> 
             <Label Grid.Row="0" Grid.Column="5" Margin="0,0,0,0" HorizontalAlignment="Center" VerticalAlignment="Center" FontWeight="Bold" Content="Condition" /> 
             <Label Grid.Row="0" Grid.Column="6" Margin="0,0,0,0" HorizontalAlignment="Center" VerticalAlignment="Center" FontWeight="Bold" Content=" Onboard&#x0a; Calibr/Test" /> 
             <Label Grid.Row="0" Grid.Column="7" Margin="0,0,0,0" HorizontalAlignment="Center" VerticalAlignment="Center" FontWeight="Bold" Content="  Shore&#x0a; Callibration" /> 
             <Label Grid.Row="0" Grid.Column="8" Margin="0,0,0,0" HorizontalAlignment="Center" VerticalAlignment="Center" FontWeight="Bold" Content="Remarks" /> 

            </Grid> 
            <Border Grid.Row="2" Grid.ColumnSpan="2" > 
            <ScrollViewer Grid.Row="2" Grid.ColumnSpan="2" CanContentScroll="True" HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto" Name="ScrollViewer3" Margin="0,0,0,0"> 
             <Grid Name="grdOnBoardCalibrationRecord" Margin="0,0,0,0"> 
              <Grid.ColumnDefinitions> 
               <ColumnDefinition Width="30"></ColumnDefinition> 
               <ColumnDefinition Width="220"></ColumnDefinition> 
               <ColumnDefinition Width="80"></ColumnDefinition> 
               <ColumnDefinition Width="80"></ColumnDefinition> 
               <ColumnDefinition Width="80"></ColumnDefinition> 
               <ColumnDefinition Width="80"></ColumnDefinition> 
               <ColumnDefinition Width="120"></ColumnDefinition> 
               <ColumnDefinition Width="120"></ColumnDefinition> 
               <ColumnDefinition Width="140*"></ColumnDefinition> 
              </Grid.ColumnDefinitions> 
              <Border Grid.Column="0" BorderThickness="1,0,1,1" BorderBrush="Black" Grid.RowSpan="26"></Border> 
              <Border Grid.Column="1" BorderThickness="0,1,1,1" Grid.RowSpan="26"></Border> 
              <Border Grid.Column="2" BorderThickness="0,1,1,1" Grid.RowSpan="26"></Border> 
              <Border Grid.Column="3" BorderThickness="0,1,1,1" Grid.RowSpan="26"></Border> 
              <Border Grid.Column="4" BorderThickness="0,1,1,1" Grid.RowSpan="26"></Border> 
              <Border Grid.Column="5" BorderThickness="0,1,1,1" Grid.RowSpan="26"></Border> 
              <Border Grid.Column="6" BorderThickness="0,1,1,1" Grid.RowSpan="26"></Border> 
              <Border Grid.Column="7" BorderThickness="0,1,1,1" Grid.RowSpan="26"></Border> 
              <Border Grid.Column="8" BorderThickness="0,1,1,1" Grid.RowSpan="26"></Border> 
             </Grid> 
            </ScrollViewer> 
            </Border> 
            <Grid Grid.Row="3" Grid.ColumnSpan="2"> 
             <Grid.RowDefinitions> 
              <RowDefinition Height="30"></RowDefinition> 
              <RowDefinition Height="30"></RowDefinition> 
              <RowDefinition Height="40"></RowDefinition> 
             </Grid.RowDefinitions> 
             <Grid.ColumnDefinitions> 
              <ColumnDefinition Width="*"></ColumnDefinition> 
             </Grid.ColumnDefinitions> 

             <TextBox Grid.Row="0" Grid.Column="0" Height="30" Width="300" TextAlignment="Center" Background="Gray" IsReadOnly="True" Margin="0,0,0,0" HorizontalAlignment="Right" VerticalAlignment="Bottom" BorderThickness="1,1,1,1" Name="txtChiefEngineer"/> 
             <Label Grid.Row="1" Grid.Column="1" Margin="0,0,100,0" HorizontalAlignment="Right" VerticalAlignment="Center" FontWeight="Bold" Content="Chief Engineer" /> 
             <StackPanel Orientation="Horizontal" Grid.Row="2" Margin="0,0,0,0" > 
              <Label Name="lblonshorecomment" Content=" Shore Comment : " HorizontalAlignment="Center" Margin="5,0,0,0" FontWeight="Bold" VerticalAlignment="Center" FontFamily="Calibri" FontStyle="Normal" FontSize="14" ></Label> 
              <TextBox BorderThickness="1" FontWeight="Normal" IsReadOnly="True" Height="44" Width="878" TextWrapping="Wrap" AcceptsReturn="True" HorizontalAlignment="left" Margin="0,0,0,0" Name="txtShoreComment" VerticalAlignment="Center" /> 
             </StackPanel> 

            </Grid> 
           </Grid> 
          </ScrollViewer> 
         </Border>` 
0

per abilitare il supporto tocco si potrebbe anche voler impostare ScrollViewer.PanningMode-None sul DataGrid e impostare la stessa proprietà a VerticalFirst o altro valore sul livello superiore ScrollViewer

Esempio

<ScrollViewer VerticalScrollBarVisibility="Auto" Margin="5" PanningMode="VerticalFirst"> 
    <DataGrid ScrollViewer.PanningMode="None" ItemsSource="{Binding Items}" /> 
</ScrollViewer> 

Naturalmente, utilizzare anche l'evento PreviewMouseWheel come indicato dalle risposte di Don B per correggere l'originale utilizzare il problema di scorrimento.

private static void ScrollViewer_PreviewMouseWheel(object sender, System.Windows.Input.MouseWheelEventArgs e) 
{ 
    var scrollViewer = (ScrollViewer)sender; 
    scrollViewer.ScrollToVerticalOffset(scrollViewer.VerticalOffset - e.Delta); 
    e.Handled = true; 
} 

Oppure, si può semplicemente impostare la seguente proprietà associata al tuo ScrollViewer

public class TopMouseScrollPriorityBehavior 
{ 
    public static bool GetTopMouseScrollPriority(ScrollViewer obj) 
    { 
     return (bool)obj.GetValue(TopMouseScrollPriorityProperty); 
    } 

    public static void SetTopMouseScrollPriority(ScrollViewer obj, bool value) 
    { 
     obj.SetValue(TopMouseScrollPriorityProperty, value); 
    } 

    public static readonly DependencyProperty TopMouseScrollPriorityProperty = 
     DependencyProperty.RegisterAttached("TopMouseScrollPriority", typeof(bool), typeof(TopMouseScrollPriorityBehavior), new PropertyMetadata(false, OnPropertyChanged)); 

    private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     var scrollViewer = d as ScrollViewer; 
     if (scrollViewer == null) 
      throw new InvalidOperationException($"{nameof(TopMouseScrollPriorityBehavior)}.{nameof(TopMouseScrollPriorityProperty)} can only be applied to controls of type {nameof(ScrollViewer)}"); 
     if (e.NewValue == e.OldValue) 
      return; 
     if ((bool)e.NewValue) 
      scrollViewer.PreviewMouseWheel += ScrollViewer_PreviewMouseWheel; 
     else 
      scrollViewer.PreviewMouseWheel -= ScrollViewer_PreviewMouseWheel; 
    } 

    private static void ScrollViewer_PreviewMouseWheel(object sender, System.Windows.Input.MouseWheelEventArgs e) 
    { 
     var scrollViewer = (ScrollViewer)sender; 
     scrollViewer.ScrollToVerticalOffset(scrollViewer.VerticalOffset - e.Delta); 
     e.Handled = true; 
    } 
} 

Uso

<ScrollViewer b:TopMouseScrollPriorityBehavior.TopMouseScrollPriority="True" VerticalScrollBarVisibility="Auto" Margin="5" PanningMode="VerticalFirst"> 
    <DataGrid ScrollViewer.PanningMode="None" ItemsSource="{Binding Items}" /> 
</ScrollViewer> 

Dove B: è il namespace che contiene questo comportamento

In questo modo il tuo no co è necessario de-behind e la tua app è puramente MVVM

Problemi correlati