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

发布于 2024-09-03 04:50:30 字数 3058 浏览 2 评论 0原文

我试图弄清楚如何让鼠标滚动在带有滚动查看器和数据网格的 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;
    }
   }

我面临的问题是,当使用鼠标滚动时,它在按钮上方时工作正常,但一旦我将鼠标指针移到网格上,尝试滚动,没有任何反应。我可以直接移动滚动查看器的滚动条。我仍然是一个 wpf 新手,因此任何关于如何让鼠标滚动在数据网格上工作的帮助将不胜感激。我猜应该有一个非常简单的解决方案,但我还没能弄清楚

I am trying to figure out how to get the mouse scroll working on a wpf window with a scrollviewer and a datagrid within it. The WPF and C# code is below

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

and the C# code is as follows

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

The problem i am facing is that when using the mouse to scroll, it works fine when it is over the button but as soon as i move the mouse pointer over the grid and try to scroll, nothing happens. I am able to move the scrollbar of the scrollviewer directly though. I am still a wpf novice so any help on how to get the mouse scroll to work over the datagrid would be appreciated. I am guessing there should be a pretty easy solution for this but I havent been able to figure it out

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(12

神妖 2024-09-10 04:50:30

我认为戴夫的解决方案是一个很好的解决方案。不过,我提出的一项建议是在滚动查看器而不是数据网格上捕获 PreviewMouseWheel 事件。如果不这样做,您可能会注意到根据您是在数据网格还是滚动条本身上滚动而产生的一些细微差异。原因是当鼠标悬停在滚动条上时,scrollviewer 将处理滚动,而当鼠标悬停在数据网格上时,datagrid 事件将处理滚动。例如,鼠标滚轮在数据网格上滚动可能会比在滚动条上滚动时使您在列表中走得更远。如果您在滚动查看器预览事件中捕获它,则所有滚动时都将使用相同的测量值。另外,如果您以这种方式捕获它,则不需要命名滚动查看器元素,因为您不需要对该对象的引用,因为您只需对传递到滚动查看器 PreviewMouseWheel 事件中的发送者对象进行类型转换。最后,我建议在事件结束时标记处理的事件,除非您出于某种原因需要在层次结构中更靠下的元素中捕获它。下面的例子:

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

I think Dave's solution is a good one. However, one recommendation I'd make is to catch the PreviewMouseWheel event on the scrollviewer instead of on the datagrid. If you don't, you might notice some minor differences based on whether you're scrolling over the datagrid or the scroll bar itself. The reasoning is that the scrollviewer will be handling scrolling when the mouse is hovered over the scrollbar, and the datagrid event will handle the scrolling when over the datagrid. For instance, one mouse wheel scroll over the datagrid might bring you farther down your list then it would when over the scroll bar. If you catch it on scrollviewer preview event, all will use the same measurement when scrolling. Also, if you catch it this way, you won't need to name the scrollviewer element, as you won't need a reference to the object since you can just type cast the sender object passed into the scrollviewer PreviewMouseWheel event. Lastly, I'd recommend marking the event handled at the end of the event, unless you need to catch it in an element further down the heirarchy for some reason. Example below:

private void ScrollViewer_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
    {
        ScrollViewer scv = (ScrollViewer)sender;
        scv.ScrollToVerticalOffset(scv.VerticalOffset - e.Delta);
        e.Handled = true;
    }
一曲爱恨情仇 2024-09-10 04:50:30

我假设 DataGrid 不需要滚动 - 在 DataGrid 上设置 VerticalScrollBar="None"。

DataGrid 吞掉了鼠标滚动事件。

我发现是使用 PreviewMouseWheel 事件来滚动要滚动的容器。您需要命名滚动查看器才能更改垂直偏移。

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

I'm assuming the DataGrid does not need to scroll - Set the VerticalScrollBar="None" on the DataGrid.

The DataGrid swallows the mouse scroll event.

What I found is to use the PreviewMouseWheel event to scroll the container that you want to scroll. You will need to name the scrollviewer to change the Vertical offset.

private void DataGrid_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
    {
       scrollViewer.ScrollToVerticalOffset(scrollViewer.VerticalOffset-e.Delta);
    }
蹲在坟头点根烟 2024-09-10 04:50:30

Don B 的解决方案的一项改进是避免使用 ScrollToVerticalOffset

scv.ScrollToVerticalOffset(scv.VerticalOffset - e.Delta);

VerticalOffset - Delta 会带来相当不和谐的体验。 ScrollViewer 花了很多心思让移动变得更加平滑。我认为它还会根据 dpi 和其他因素缩小增量...

我发现最好捕获并处理 PreviewMouseWheelEvent 并将 MouseWheelEvent 发送到预期的 滚动查看器。我的 Don B 解决方案版本如下所示。

private void ScrollViewer_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
{
    var eventArg = new MouseWheelEventArgs(e.MouseDevice, e.Timestamp, e.Delta);
    eventArg.RoutedEvent = UIElement.MouseWheelEvent;
    eventArg.Source = e.Source;

    ScrollViewer scv = (ScrollViewer)sender;
    scv.RaiseEvent(eventArg);
    e.Handled = true;
}

An improvement to Don B's solution is to avoid using ScrollToVerticalOffset.

scv.ScrollToVerticalOffset(scv.VerticalOffset - e.Delta);

VerticalOffset - Delta results in a pretty jarring experience. The ScrollViewer puts a lot of thought into making the movement smoother than that. I think it also scales the delta down based on dpi and other factors...

I found it's better to catch and handle the PreviewMouseWheelEvent and send a MouseWheelEvent to the intended ScrollViewer. My version of Don B's solution looks like this.

private void ScrollViewer_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
{
    var eventArg = new MouseWheelEventArgs(e.MouseDevice, e.Timestamp, e.Delta);
    eventArg.RoutedEvent = UIElement.MouseWheelEvent;
    eventArg.Source = e.Source;

    ScrollViewer scv = (ScrollViewer)sender;
    scv.RaiseEvent(eventArg);
    e.Handled = true;
}
春风十里 2024-09-10 04:50:30

要启用触摸支持,您可能还需要在 DataGrid 上将 ScrollViewer.PanningMode 设置为 None,并将相同的属性设置为 VerticalFirst< /code> 或顶级 ScrollViewer 上的其他值

示例

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

当然,也可以使用 Don B 的答案所示的 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

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

Usage

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

其中 b: 是包含此行为的命名空间

这样您的应用程序就不需要任何代码隐藏纯粹是MVVM

To enable touch support you might also want to set ScrollViewer.PanningMode to None on your DataGrid and set the same property to VerticalFirst or other value on your top level ScrollViewer

Example

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

Of course, also use the PreviewMouseWheel event as indicated by Don B's answers to fix the original mouse scrolling issue.

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

Or, you can simply set the following Attached Property to your 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;
    }
}

Usage

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

Where b: is the namespace that contains this behavior

This way your no code-behind is needed and your app is purely MVVM

关于从前 2024-09-10 04:50:30

我尝试了 Don B 的解决方案,它很好地解决了当您没有其他内部可滚动控件时在数据网格上滚动的问题。

对于滚动查看器具有其他可滚动控件和数据网格作为子项的情况,则要求该事件不应在主滚动查看器的事件处理程序末尾标记为已处理,以便也可以在内部可滚动控件,但是这有一个副作用,即当滚动仅发生在内部可滚动控件上时,它也会发生在主滚动查看器上。

因此,我更新了戴夫的解决方案,其中滚动查看器的发现方式有所不同,因此无需知道滚动查看器的名称:

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

I tried Don B's solution and it's solves the issue with scrolling over a data grid pretty well for the cases when you don't have other inner scrollable controls.

For the case when the scroll viewer has as children other scrollable controls and a data grid, then that requires that the event shouldn't be marked as handled at the end of the event handler for the main scroll viewer so it could be catched also in the inner scrollable controls, however that has the side effect that when the scroll should occur only on the inner scrollable control, it will also occur on the main scroll viewer.

So I've updated Dave's solution with the difference for how the scroll viewer is found so it won't be necessary to know the name of the scroll viewer:

private void DataGrid_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
{
    ScrollViewer scrollViewer = (((DependencyObject)sender).GetVisualParent<ScrollViewer>());
    scrollViewer.ScrollToVerticalOffset(scrollViewer.VerticalOffset - e.Delta);
}
生生漫 2024-09-10 04:50:30

@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 存在,这可以防止外部滚动器滚动。

@fjch1997, I used your solution and it works pretty well.
There is only one problem which I found. It's connected with the comment of @Vadim Tofan:

For the case when the scroll viewer has as children other scrollable
controls and a data grid, then that requires that the event shouldn't
be marked as handled at the end of the event handler for the main
scroll viewer so it could be catched also in the inner scrollable
controls, however that has the side effect that when the scroll should
occur only on the inner scrollable control, it will also occur on the
main scroll viewer.

I also tried to remove e.Handled = true statement, but then the effect is not nice - both scrolls are moved in the same time. So, finally I enhanced a little bit event handler method to the following one:

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

This now prevents the outside scroller to scroll in case inner ScrollViewer exists.

清风不识月 2024-09-10 04:50:30

伙计们,我已经看到了这里发布的大部分解决方案,基本上所有解决方案都是正确的,但我认为我们可以应用一种最简单、更优雅的语法。

假设我们不需要滚动我们的数据网格,而是我们想滚动我们的主窗口

“Dave”和“Vladim Tofan”答案

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

抱歉,英语不好。

Guys I`ve seen most of the solution posted over here and fundamentally all of them are right, but I think there is an easiest and more elegant syntax that we could apply.

Assuming that we don't need to scroll with our data grid and instead we would like to scroll with our MainWindow

fallowing "Dave" and "Vladim Tofan" answer

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

Sorry, for bad english.

情话墙 2024-09-10 04:50:30

下面是创建滚动 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 方法。

Here is a larger example of creating a WPF behavior that scrolls the DataGrid.

First define the following base class for gluing together framework element with behavior class and its behavior implementation.

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

    }

}

This looks a bit more complex, but it simplifies boiler plate coding when it comes to gluing together the behavior class with the framework element. In this particular case we will not need to use an associated command.

Our scroll viewer behavior then looks like this:

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

In XAML we then can first define the namespaces:

xmlns:local="clr-namespace:SomeAcme.Client.Infrastructure"
xmlns:sys="clr-namespace:System;assembly=mscorlib"

Finally we are ready to use the mouse wheel scroll by using the WPF behavior in the XAML.

..

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

I have tested and verified that this approach works. For developers working with a WPF app, utilizing WPF behaviors keeps amount of code in code behind still to the minimum bits and staying faitfully to the MVVM approach.

南风几经秋 2024-09-10 04:50:30

Grid 有一个内置的 ScrollPanel,因此用 ScrollPanel 包裹它对我来说根本不起作用(使 Grid 具有固定高度是不可能的,因为我希望它能够与应用程序的其余部分一起很好地调整大小)。

我所做的是这里一些评价较高的解决方案的组合,但本质上的想法是摆脱 ScrollPanel 并将 DataGrid 的 PreviewMouseEvent 通过管道返回到实际处理滚动的父控件(在我的如果是网格)。

    private void DataGrid_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
    {

        MouseWheelEventArgs eventArg = new MouseWheelEventArgs(e.MouseDevice, e.Timestamp, e.Delta)
        {
            RoutedEvent = MouseWheelEvent, Source = e.Source
        };
        DependencyObject parent = VisualTreeHelper.GetParent((DependencyObject) sender);

        while (parent != null && !(parent is Grid))
        {
            parent = VisualTreeHelper.GetParent(parent);
        }

        if (parent != null)
        {
            Grid grid = (Grid) parent;
            grid.RaiseEvent(eventArg);
        }

        e.Handled = true;
    }

The Grid has a built in ScrollPanel so wrapping it with a ScrollPanel didn't work at all for me (making the Grid of fixed height was out of the question because I wanted it to resize nicely with the rest of the application).

What I did was a combination of a few of the higher rated solutions in here, but essentially the idea is to get rid of the ScrollPanel and just pipe the PreviewMouseEvent of the DataGrid back to the parent control that is actually handling the scrolling (in my case it was a Grid).

    private void DataGrid_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
    {

        MouseWheelEventArgs eventArg = new MouseWheelEventArgs(e.MouseDevice, e.Timestamp, e.Delta)
        {
            RoutedEvent = MouseWheelEvent, Source = e.Source
        };
        DependencyObject parent = VisualTreeHelper.GetParent((DependencyObject) sender);

        while (parent != null && !(parent is Grid))
        {
            parent = VisualTreeHelper.GetParent(parent);
        }

        if (parent != null)
        {
            Grid grid = (Grid) parent;
            grid.RaiseEvent(eventArg);
        }

        e.Handled = true;
    }
荒路情人 2024-09-10 04:50:30

我发现了这个: http://wpfthoughts.blogspot.com/ 2014/05/datagrid-vertical-scrolling-issues.html 并认为我应该将其添加到此处。
“如果您的目标是 Framework 4.5,则 DataGrid 的内部 VirtualizingPanel 上有一个名为 ScrollUnit 的新依赖项对象,可以将其设置为 Item(默认值)或 Pixel。如果我们稍微修改一下 XAML,我们就可以看到它是如何工作的。”

<DataGrid Name="DG" ItemsSource="{Binding B0}" AutoGenerateColumns="False" IsReadOnly="true" RowDetailsVisibilityMode="Visible" Width="200" 
      Height="100" VirtualizingPanel.ScrollUnit="Pixel">

I found this: http://wpfthoughts.blogspot.com/2014/05/datagrid-vertical-scrolling-issues.html and thought I should add it here.
"If you are targeting Framework 4.5 there is a new dependency object on the DataGrid's internal VirtualizingPanel called ScrollUnit that can be set to Item (the default) or Pixel. If we modify the XAML a little we can see how it works."

<DataGrid Name="DG" ItemsSource="{Binding B0}" AutoGenerateColumns="False" IsReadOnly="true" RowDetailsVisibilityMode="Visible" Width="200" 
      Height="100" VirtualizingPanel.ScrollUnit="Pixel">
云雾 2024-09-10 04:50:30

我知道已经有一段时间了,但我遇到了同样的问题并使用 DockPanel 解决了它。

<DockPanel Grid.ColumnSpan="3" LastChildFill="True">
    <Button DockPanel.Dock="Top" Content="Add" Grid.Column="3" HorizontalAlignment="Right" Width="110" Height="30" Margin="5"/>
    <DataGrid x:Name="xxDG" SelectionUnit="Cell" ItemsSource="{Binding}" Margin="0, 0, 0, 0" >
        ...   
    </DataGrid>
</DockPanel>

出于某种原因,它可以像魅力一样处理鼠标滚轮事件。

I know it's been a while, but I met the same issue and solved it with DockPanel

<DockPanel Grid.ColumnSpan="3" LastChildFill="True">
    <Button DockPanel.Dock="Top" Content="Add" Grid.Column="3" HorizontalAlignment="Right" Width="110" Height="30" Margin="5"/>
    <DataGrid x:Name="xxDG" SelectionUnit="Cell" ItemsSource="{Binding}" Margin="0, 0, 0, 0" >
        ...   
    </DataGrid>
</DockPanel>

For some reason this handles the mouse wheel events like a charm.

魔法唧唧 2024-09-10 04:50:30

我发现 ScrollViewer 无法连接,这意味着如果它像您的情况一样连接,则网格在 ScrollViewer 标记下开始,并且在网格中我们有 DataGrid,并且在 DataGrid 中再次设置了 ScrollViewer 属性。 IE

  <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.
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
 Calibr/Test" />

        <Label  Grid.Row="0"
                Grid.Column="7"
                Margin="0,0,0,0"
                HorizontalAlignment="Center"
                VerticalAlignment="Center"
                FontWeight="Bold"
                Content="     Shore
 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>

I found that ScrollViewer can't be concatenated, which means if it is concatenated like in your case the Grid starts under the ScrollViewer tag and in the Grid we have DataGrid and in the DataGrid again the ScrollViewer property has been set. i.e.

  <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.
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
 Calibr/Test" />

        <Label  Grid.Row="0"
                Grid.Column="7"
                Margin="0,0,0,0"
                HorizontalAlignment="Center"
                VerticalAlignment="Center"
                FontWeight="Bold"
                Content="     Shore
 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>

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文