选择时DataGrid会自动滚动

时间:2014-11-11 16:23:46

标签: c# wpf datagrid

我有一个自定义Datagrid,在datagrid中我改变了选择元素的方式。
我在选择中添加了一些功能,例如:

      
  • 当我们选择元素时,它就像" Ctrl"关键是按。
  •   
  • 当我们点击选定的行时,该行将被取消选中。
  •   
  • 当我们进行多重选择时,所有行都会更改第一行所具有的selectedValue。
  •   
  • 当我们进行多项选择(鼠标按下,移动,然后鼠标按下)时,右键单击它可以反转行的选定值。
  

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

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

    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 Handler来实现它,但是现在我卡住了因为我不知道该怎么做。

1 个答案:

答案 0 :(得分:0)

我终于通过尝试错误尝试找到了解决方案。我添加了方法来获取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;
    }
}