【问题标题】:DataGrid auto scrolling when doing selection选择时DataGrid自动滚动
【发布时间】:2015-01-08 06:36:36
【问题描述】:

我有一个自定义数据网格,在该数据网格中我改变了我们选择元素的方式。
我在选择中添加了一些功能,例如:

  • 当我们选择元素时,就像按下了“Ctrl”键。
  • 当我们单击选定的行时,该行将变为未选中状态。
  • 当我们进行多项选择时,所有行都会将 selectedValue 更改为第一行将拥有的那个。
  • 当我们通过右键单击进行多项选择(鼠标向下、移动,然后鼠标向上)时,它会反转所选行的值。

这是一个 DataGrid 扩展,所以我只用 C# 编码。

为此,我在 PreviewMouseDown 和 MouseUp 上为 datagridrow 添加了事件句柄。

    private enum ButtonClicked {Left, Middle, Right};
    private ButtonClicked m_oMouseButtonClicked;
    private void PreviewMouseDownHandler(object sender, MouseButtonEventArgs e)
    {
        DataGridRow row = sender as DataGridRow;

        if (e.LeftButton == MouseButtonState.Pressed)
        {
            row.IsSelected = !row.IsSelected;
            m_oMouseButtonClicked = ButtonClicked.Left;
        }
        else if (e.RightButton == MouseButtonState.Pressed)
        {
            //row.IsSelected = !row.IsSelected;
            m_oMouseButtonClicked = ButtonClicked.Right;
        }

        row.CaptureMouse();
        row.MouseMove += row_MouseMove;

        e.Handled = true;
    }

    void row_MouseMove(object sender, MouseEventArgs e)
    {
        Point oPosFromThis = e.GetPosition(this);

        if (oPosFromThis.Y > this.ActualHeight)
        {
        }
        else if (oPosFromThis.Y < 0)
        {
        }
    }

    void Row_MouseUp(object sender, MouseButtonEventArgs e)
    {
        int nStart;
        int nEnd;

        DataGridRow row = sender as DataGridRow;
        row.ReleaseMouseCapture();
        row.MouseMove -= row_MouseMove;

        int nStartRowIndex = ItemContainerGenerator.IndexFromContainer(row);


        Point oPosFromRow = e.MouseDevice.GetPosition(row);
        int nEndRowIndex = nStartRowIndex + (int)Math.Floor(oPosFromRow.Y / row.ActualHeight);


        if (nStartRowIndex < nEndRowIndex)
        {
            nStart = Math.Max(nStartRowIndex, 0);
            nEnd = Math.Min(nEndRowIndex, Items.Count - 1);
        }
        else 
        {
            nStart = Math.Max(nEndRowIndex, 0);
            nEnd = Math.Min(nStartRowIndex, Items.Count - 1);
        }

        for (; nStart <= nEnd; ++nStart)
        {
            DataGridRow oTmp = ((DataGridRow)ItemContainerGenerator.ContainerFromIndex(nStart));
            if (m_oMouseButtonClicked == ButtonClicked.Left)
            {
                oTmp.IsSelected = row.IsSelected;
            }
            else if (m_oMouseButtonClicked == ButtonClicked.Right)
            {
                oTmp.IsSelected = !oTmp.IsSelected;
            }
        }

        e.Handled = true;
    }

我将鼠标捕捉到我单击的行,以便即使我离开数据网格也能捕捉到 mouseUp。

但是使用我的代码,我失去了我想要拥有的功能。当我进行多项选择并且我在数据网格下方或上方时自动滚动。我知道我必须添加 MouseMove 处理程序才能做到这一点,但现在我被卡住了,因为我不知道该怎么做。

【问题讨论】:

    标签: c# wpf datagrid


    【解决方案1】:

    我终于通过尝试错误尝试找到了解决方案。我添加了获取 scrollviewer 元素的方法,然后我启动了一个 Timer 来单独执行滚动。

    public claa AAA
    {
        private enum ButtonClicked {Left, Middle, Right};
    
        private ButtonClicked m_oMouseButtonClicked;
    
        private DispatcherTimer m_oTimer;
    
        private double m_nScrollOffset;
    
        private ScrollViewer m_oScrollBar;
    
    
    
        public IcuAlertGrid()
        {
            this.Initialized += IcuAlertGrid_Initialized;
            this.Loaded += IcuAlertGrid_Loaded;
    
            m_oTimer = new DispatcherTimer();
            m_oTimer.Tick += m_oTimer_Tick;
            m_oTimer.Interval = new TimeSpan(2500000);
        }
    
        void IcuAlertGrid_Initialized(object sender, EventArgs e)
        {
            setStyle0(true);
            //throw new NotImplementedException();
        }
    
        void IcuAlertGrid_Loaded(object sender, RoutedEventArgs e)
        {
            m_oScrollBar = GetScrollViewer(this);
        }
    
        void m_oTimer_Tick(object sender, EventArgs e)
        {
            if (m_oScrollBar != null)
            {
                m_oScrollBar.ScrollToVerticalOffset(m_oScrollBar.VerticalOffset + m_nScrollOffset);
            }
        }
    
        private void PreviewMouseDownHandler(object sender, MouseButtonEventArgs e)
        {
            DataGridRow row = sender as DataGridRow;
    
            if (e.LeftButton == MouseButtonState.Pressed)
            {
                row.IsSelected = !row.IsSelected;
                m_oMouseButtonClicked = ButtonClicked.Left;
            }
            else if (e.RightButton == MouseButtonState.Pressed)
            {
                //row.IsSelected = !row.IsSelected;
                m_oMouseButtonClicked = ButtonClicked.Right;
            }
    
            row.CaptureMouse();
            row.MouseMove += row_MouseMove;
    
            e.Handled = true;
        }
    
        private void row_MouseMove(object sender, MouseEventArgs e)
        {
            DataGridRow oRow = sender as DataGridRow;
            Point oPosFromThis = e.GetPosition(this);
    
            if (oPosFromThis.Y < 0)
            {
                m_nScrollOffset = -1.0;
                m_oTimer.Start();
            } 
            else if (this.ActualHeight < oPosFromThis.Y)
            {
                m_nScrollOffset = 1.0;
                m_oTimer.Start();
            } 
            else
            {
                m_oTimer.Stop();
            }
        }
    
        private void Row_MouseUp(object sender, MouseButtonEventArgs e)
        {
            int nStart;
            int nEnd;
    
            m_oTimer.Stop();
    
            DataGridRow row = sender as DataGridRow;
            row.ReleaseMouseCapture();
            row.MouseMove -= row_MouseMove;
    
            int nStartRowIndex = ItemContainerGenerator.IndexFromContainer(row);
            Point oPosFromRow = e.MouseDevice.GetPosition(row); 
            int nEndRowIndex = nStartRowIndex + (int)Math.Floor(oPosFromRow.Y / row.ActualHeight);
    
    
            if (nStartRowIndex < nEndRowIndex)
            {
                nStart = Math.Max(nStartRowIndex, 0);
                nEnd = Math.Min(nEndRowIndex, Items.Count - 1);
            }
            else
            {
                nStart = Math.Max(nEndRowIndex, 0);
                nEnd = Math.Min(nStartRowIndex, Items.Count - 1);
            }
    
            for (; nStart <= nEnd; ++nStart)
            {
                DataGridRow oTmp = ((DataGridRow)ItemContainerGenerator.ContainerFromIndex(nStart));
                if (m_oMouseButtonClicked == ButtonClicked.Left)
                {
                    oTmp.IsSelected = row.IsSelected;
                }
                else if (m_oMouseButtonClicked == ButtonClicked.Right)
                {
                    oTmp.IsSelected = !oTmp.IsSelected;
                }
            }
            e.Handled = true;
        }
    
        private static ScrollViewer GetScrollViewer(DependencyObject p_oParent) 
        {
            ScrollViewer child = default(ScrollViewer);
    
            int numVisuals = VisualTreeHelper.GetChildrenCount(p_oParent);
    
            for (int i = 0; i < numVisuals; i++)
            {
                Visual v = (Visual)VisualTreeHelper.GetChild(p_oParent, i);
                child = v as ScrollViewer;
    
                if (child == null)
                {
                    child = GetScrollViewer(v);
                }
    
                if (child != null)
                {
                    break;
                }
            }
    
            return child;
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2011-11-26
      • 1970-01-01
      • 1970-01-01
      • 2012-08-07
      • 1970-01-01
      • 2013-04-08
      • 1970-01-01
      • 1970-01-01
      • 2019-09-13
      相关资源
      最近更新 更多