Подтвердить что ты не робот

Прокрутка мыши не работает в средстве просмотра прокрутки с помощью wpf datagrid и дополнительных элементов пользовательского интерфейса

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

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

и код С# выглядит следующим образом

 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, будет оценена по достоинству. Я предполагаю, что для этого должно быть довольно простое решение, но я не смог понять это.

4b9b3361

Ответ 1

Я думаю, что решение Dave является хорошим. Тем не менее, одна рекомендация, которую я сделал бы, заключается в том, чтобы поймать событие 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;
    }

Ответ 2

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

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

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

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

Ответ 3

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

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

Итак, я обновил решение Dave с разницей в том, как просматривается средство просмотра прокрутки, поэтому нет необходимости знать имя прокрутки:

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

Ответ 4

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

Пример

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

Конечно, также используйте событие PreviewMouseWheel, как указано ответами Don B, чтобы исправить исходную проблему прокрутки мыши.

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>

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

Таким образом, ваш код не нужен, а ваше приложение - это просто MVVM

Ответ 5

@fjch1997, я использовал ваше решение, и оно работает довольно хорошо. Есть только одна проблема, которую я обнаружил. Это связано с комментарием @Vadim Tofan:

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

Я также попытался удалить e.Handled = true, но тогда эффект не из приятных - оба свитка перемещаются одновременно. Итак, наконец-то я немного усовершенствовал метод обработчика событий до следующего:

private static void ScrollViewer_PreviewMouseWheel(object sender, System.Windows.Input.MouseWheelEventArgs e)
{
    ScrollViewer scrollViewer = (ScrollViewer)sender;
    FrameworkElement origicalControlSender = e.OriginalSource as FrameworkElement;

    ScrollViewer closestScrollViewer = origicalControlSender.GetParent<ScrollViewer>();

    if (closestScrollViewer != null && !ReferenceEquals(closestScrollViewer, scrollViewer))
    {
        return;
    }

    scrollViewer.ScrollToVerticalOffset(scrollViewer.VerticalOffset - e.Delta);
    e.Handled = true;
}

public static T GetParent<T>(this FrameworkElement control)
    where T : DependencyObject
{
    FrameworkElement parentElement = control?.Parent as FrameworkElement;

    if (parentElement == null)
    {
        return null;
    }

    T parent = parentElement as T;

    if (parent != null)
    {
        return parent;
    }

    return GetParent<T>(parentElement);
}

Это теперь предотвращает прокрутку внешнего скроллера в случае, если существует внутренний ScrollViewer.

Ответ 6

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

Предполагая, что нам не нужно прокручивать нашу сетку данных, а вместо этого мы хотели бы прокручивать наше MainWindow

парящий ответ "Дэйв" и "Владимир Тофан"

Private Void Scrlll(Object sebder, MouseWheelEventArgs e)
{
   var windows = (Window.GetWindow(this) as MainWindow).MainScroll;
   windows.ScrollToVerticalOffset(windows.VerticalOffset - e.Delta);
}

Извините за плохой английский.

Ответ 7

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

  <Grid>
     <Grid.RowDefinitions>
        <RowDefinition Height="30" />
        <RowDefinition Height="45" />
        <RowDefinition Height="100*" />
        <RowDefinition Height="105" />
     </Grid.RowDefinitions>
     <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*" />
        <ColumnDefinition Width="*" />
     </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" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
           <ColumnDefinition Width="30" />
           <ColumnDefinition Width="220" />
           <ColumnDefinition Width="80" />
           <ColumnDefinition Width="80" />
           <ColumnDefinition Width="80" />
           <ColumnDefinition Width="80" />
           <ColumnDefinition Width="120" />
           <ColumnDefinition Width="120" />
           <ColumnDefinition Width="140*" />
        </Grid.ColumnDefinitions>

        <Border BorderBrush="Black"
                BorderThickness="0,1,1,1"
                Grid.Row="0"
                Grid.Column="0" />
        <Border BorderBrush="Black"
                BorderThickness="0,1,1,1"
                Grid.Row="0"
                Grid.Column="1" />
        <Border BorderBrush="Black"
                BorderThickness="0,1,1,1"
                Grid.Row="0"
                Grid.Column="2" />
        <Border BorderBrush="Black"
                BorderThickness="0,1,1,1"
                Grid.Row="0"
                Grid.Column="3" />
        <Border BorderBrush="Black"
                BorderThickness="0,1,1,1"
                Grid.Row="0"
                Grid.Column="4" />
        <Border BorderBrush="Black"
                BorderThickness="0,1,1,1"
                Grid.Row="0"
                Grid.Column="5" />
        <Border BorderBrush="Black"
                BorderThickness="0,1,1,1"
                Grid.Row="0"
                Grid.Column="6" />
        <Border BorderBrush="Black"
                BorderThickness="0,1,1,1"
                Grid.Row="0"
                Grid.Column="7" />
        <Border BorderBrush="Black"
                BorderThickness="0,1,1,1"
                Grid.Row="0"
                Grid.Column="8" />

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