滚动鼠标在带有WPF数据表格和其他UI元素的滚动查看器中不起作用

48

我正在尝试找出如何在一个带有ScrollViewer和DataGrid的WPF窗口上使鼠标滚动正常工作。以下是WPF和C#代码:

<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中起作用的任何帮助。我猜这个问题应该有一个很简单的解决方案,但我还没能搞定。


我遇到了完全相同的问题,但是下面的解决方案在MVVM应用程序中不太好用。我们的架构师不希望在视图中有任何代码,只允许使用Xaml或Behaviors。 - Kolky
1
嗨Kolky,我知道这个答案对你来说可能太晚了,已经有将近6年了,但是也许对于其他处在类似情况的人会有用。通常,像这样的UI类型逻辑可以使用MVVM模式实现,例如使用代码后台类(code behind class)。这是一个关于它的MSDN文章链接:https://msdn.microsoft.com/en-us/library/gg405484(v=pandp.40).aspx - Don B
12个回答

0

这是一个更大的示例,演示如何创建一个滚动DataGrid的WPF行为。

首先定义以下基类,用于将框架元素与行为类及其行为实现粘合在一起。

using System.Diagnostics.CodeAnalysis;
using System.Windows;
using System.Windows.Input;

namespace SomeAcme.Client.Infrastructure
{


    /// <summary>
    /// Behavior handler class for creating WPF behaviors.
    /// </summary>  
     [ExcludeFromCodeCoverage] 
    public class BehaviorHandler<TAssociatedObject, TBehaviorClass> 
        where TAssociatedObject: DependencyObject
        where TBehaviorClass : class, IAssociationBehavior, new()
    {

        public BehaviorHandler()
        {
        }

        public static TBehaviorClass GetBehavior(DependencyObject obj)
        {
            if (obj == null)
                return null; 

            return (TBehaviorClass)obj.GetValue(BehaviorProperty);
        }

        public static void SetBehavior(DependencyObject obj, TBehaviorClass value)
        {
            if (obj != null)
            {
                obj.SetValue(BehaviorProperty, value);
            }
        }

        // Using a DependencyProperty as the backing store for Behavior.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty BehaviorProperty =
            DependencyProperty.RegisterAttached("Behavior", typeof(TBehaviorClass), typeof(object), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.Inherits));


        public void FindOrCreateBehaviorOnDemand(DependencyObject dependencyObject)
        {
             //Apply the behavior 
             TBehaviorClass behavior = FindOrCreateBehavior(dependencyObject);
             if (behavior != null)
             {
                 dependencyObject.SetValue(BehaviorProperty, behavior); 
             }
        }

        public TBehaviorClass FindOrCreateBehavior(DependencyObject dependencyObject)
        {
            if (dependencyObject == null)
                return null;
            var associatedObject = dependencyObject;
            if (associatedObject == null)
                return null;
            var behavior = dependencyObject.GetValue(BehaviorProperty) as TBehaviorClass;
            if (behavior == null)
            {
                var behaviorAssociated = new TBehaviorClass();
                if (behaviorAssociated == null)
                    return null;
                behaviorAssociated.InitializeAssociation(associatedObject, AssociatedCommands);
                return behaviorAssociated;
            }
            else
            {
                return behavior;
            }
        } //TBehaviorClass FindOrCreateBehavior 

        /// <summary>
        /// Set the associated commands to pass into the WPF behavior, if desired
        /// </summary>
        public ICommand[] AssociatedCommands { get; set; }

    }

}

这看起来有点复杂,但是当涉及到将行为类与框架元素粘合在一起时,它简化了样板代码。在这种特定情况下,我们将不需要使用关联命令。

我们的滚动查看器行为看起来像这样:

    using SomeAcme.Client.Infrastructure;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Input;

    namespace SomeAcme.Client.Infrastructure
    {

        public static class ScrollViewerMouseWheelScrollBehavior
        {


                public static string GetUseMouseScrollForScrollViewer(DependencyObject obj)
                {
                    if (obj != null)
                    {
                        return (string)obj.GetValue(UseMouseScrollForScrollViewerProperty);
                    }
                    else
                        return null;
                }

                public static void SetUseMouseScrollForScrollViewer(DependencyObject obj, string value)
                {
                    if (obj != null)
                    {
                        obj.SetValue(UseMouseScrollForScrollViewerProperty, value);
                    }
                }


 public static readonly DependencyProperty UseMouseScrollForScrollViewerCommandProperty =
                    DependencyProperty.RegisterAttached("UseScrollForScrollViewer", typeof(string), typeof(ScrollViewerMouseWheelScrollBehavior),
                        new PropertyMetadata(new PropertyChangedCallback(OnUseScrollForScrollViewerSet)));

                public static void OnUseScrollForScrollViewerSet(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs eventArgs)
                {
                    bool useScroll;
                    bool.TryParse(eventArgs.NewValue?.ToString(), out useScroll);
                    if (useScroll)
                    {
                        var behaviorHandler =
                            new BehaviorHandler<ScrollViewer, ScrollViewerMouseScrollBehaviorImplementation>();
                        //behaviorHandler.AssociatedCommands = 
                        //    new Microsoft.Practices.Prism.Commands.DelegateCommand<object>[] { (Microsoft.Practices.Prism.Commands.DelegateCommand<object>)eventArgs.NewValue };
                        behaviorHandler.FindOrCreateBehaviorOnDemand(dependencyObject);
                    }
                }

            }

    }

    namespace SomeAcme.Client.Infrastructure
    {
        public class ScrollViewerMouseScrollBehaviorImplementation : IAssociationBehavior
        {
            public void InitializeAssociation(DependencyObject associatedObject, params ICommand[] commands)
            {
                //TODO: Add commands to associate
                var scrollViewer = associatedObject as ScrollViewer;
                if (scrollViewer != null)
                {
                    scrollViewer.PreviewMouseWheel += ScrollViewer_PreviewMouseWheel;
                }
            }

            private void ScrollViewer_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
            {
                var scrollViewer = sender as ScrollViewer;
                if (scrollViewer != null)
                {
                    scrollViewer.ScrollToVerticalOffset(scrollViewer.VerticalOffset - e.Delta);
                }
            }
        }
    }

在XAML中,我们可以先定义命名空间:
xmlns:local="clr-namespace:SomeAcme.Client.Infrastructure"
xmlns:sys="clr-namespace:System;assembly=mscorlib"

最后我们已经准备好通过在XAML中使用WPF行为来使用鼠标滚轮滚动。

..

 <TabControl Grid.Row="1">
        <TabItem Header="Skjemafelter">
            <ScrollViewer Height="700" local:ScrollViewerMouseWheelScrollBehavior.UseMouseScrollForScrollViewer="{x:Static sys:Boolean.TrueString}">
                <ListView x:Name="ColumnsListView" ItemsSource="{Binding CurrentFields}">
                    <ListView.View>
                        <GridView>

我已经测试并验证了这种方法的可行性。对于使用 WPF 应用程序的开发人员,利用 WPF 行为可以将代码后台中的代码量最小化,并忠实地遵循 MVVM 方法。


-1
我发现 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>


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接