2010-05-27 3 views
23

Я пытаюсь выяснить, как заставить прокрутку мыши работать с окном wpf с помощью scrollviewer и datagrid внутри него. WPF и C# код нижеПрокрутка мыши не работает в средстве просмотра прокрутки с wpf datagrid и дополнительными элементами пользовательского интерфейса

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

и C# код следующим

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

Проблема я столкнулся в том, что при использовании мыши для прокрутки, она прекрасно работает, когда она над , но как только я переместите указатель мыши над сеткой и попробую прокрутить, ничего не произойдет. Однако я могу перемещать полосу прокрутки scrollviewer. Я по-прежнему новичок в wpf, поэтому любая помощь в том, как получить прокрутку мыши для работы над datagrid, будет оценена по достоинству. Я предполагаю, что для этого должно быть довольно простое решение, но я не смог это выяснить.

+0

У меня такая же проблема, однако нижеприведенные решения не очень хорошо работают в приложении MVVM. Наш архитектор не хочет иметь никакого кода в представлениях, только Xaml или Behaviors. – Kolky

+0

Привет, Колки, я знаю, что этот ответ, вероятно, слишком поздно для вас, почти 6 лет, но, возможно, это будет полезно для кого-то другого в подобной ситуации. Обычно логика типа UI, подобная этому, приемлема с использованием шаблона MVVM, например, с использованием кода за классом. Вот ссылка на статью MSDN на нем: https://msdn.microsoft.com/en-us/library/gg405484(v=pandp.40).aspx –

ответ

11

Я предполагаю, что DataGrid не нужно прокручивать - установите VerticalScrollBar = «Нет» в DataGrid.

DataGrid проглатывает событие прокрутки мыши.

То, что я нашел, это использовать событие PreviewMouseWheel для прокрутки контейнера, который вы хотите прокрутить. Вам нужно будет назвать scrollviewer для изменения смещения по вертикали.

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

Я думаю, что решение Дейва является хорошим. Тем не менее, одна рекомендация, которую я сделал бы, заключается в том, чтобы поймать событие PreviewMouseWheel на scrollviewer, а не на datagrid. Если вы этого не сделаете, вы можете заметить некоторые незначительные отличия в зависимости от того, прокручиваетесь ли вы за панель данных или панель прокрутки. Причиной является то, что scrollviewer будет обрабатывать прокрутку, когда мышь зависает над полосой прокрутки, а событие datagrid будет обрабатывать прокрутку по сравнению с datagrid. Например, одно колесо мыши, прокручивающееся по datagrid, может привести вас дальше по вашему списку, а затем по полосе прокрутки. Если вы поймаете его на событии предварительного просмотра scrollviewer, все будут использовать одно и то же измерение при прокрутке. Кроме того, если вы поймаете его таким образом, вам не нужно будет указывать элемент scrollviewer, так как вам не понадобится ссылка на объект, поскольку вы можете просто начертить передачу объекта отправителя, переданного в событие PreviewMouseWheel scrollviewer. Наконец, я бы рекомендовал пометить событие, обработанное в конце события, если вам почему-то не понадобится поймать его в элементе, расположенном дальше по иерархии. Пример ниже:

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

Я попытался решением Дона B и это решает проблему с прокруткой по сетке данных очень хорошо для тех случаев, когда у вас нет другого внутренней прокрутку управления.

Для случая, когда средство просмотра прокрутки имеет в качестве дочерних элементов другие прокручиваемые элементы управления и сетку данных, тогда это требует, чтобы событие не было помечено как обработано в конце обработчика событий для основного средства просмотра прокрутки, чтобы оно могло также попадаются во внутренние прокручиваемые элементы управления, однако это имеет побочный эффект, когда свиток должен выполняться только на внутреннем прокручиваемом элементе управления, он также будет отображаться в основном средстве просмотра прокрутки.

Так я обновил решение Дэйва с разницей в том, как можно найти зрителя прокрутки, так что не нужно будет знать имя просмотра прокрутки:

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

Было бы еще лучше, если бы это не зависело от сторонняя библиотека. – linac

+1

Что такое сторонняя библиотека? Это встроенные средства управления WPF. –

+0

'GetVisualParent' - нет. – linac

0

Я также МОФ новичок и застрял в той же проблеме

i.e, используя мышь для прокрутки, она отлично работает, когда она находится над кнопкой, но как только вы перемещаете указатель мыши по сетке и пытаетесь прокручивать, ничего не происходит.

Но благодаря моему способу работы, то есть пойдите на лишнюю милю, и я обнаружил, что ScrollViewer нельзя конкатенировать, означает, что он объединен, как в вашем случае, сетка начинается под тегом ScrollViewer, а в гриде у нас есть DataGrid а в DataGrid снова установлено свойство ScrollViewer. т.е.

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

Чтобы включить сенсорную поддержку, которую вы также можете установить ScrollViewer.PanningMode к None на вашем DataGrid и установить тот же свойство VerticalFirst или другое значение на вашем верхнем уровне ScrollViewer

Пример

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

Конечно, также используйте событие PreviewMouseWheel, как указано в ответах Дона Б, чтобы исправить первоначальный mo используйте прокрутку.

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

Или, вы можете просто установить следующую вложенное свойство к вашему 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; 
    } 
} 

Использование

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

Где б: это пространство имен, которое содержит такое поведение

Таким образом, de-behind необходимо, и ваше приложение чисто MVVM