Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C#
  4. Linking the scroll bars of two controls

Linking the scroll bars of two controls

Scheduled Pinned Locked Moved C#
comc++helptutorialquestion
9 Posts 3 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • D Offline
    D Offline
    Dewald
    wrote on last edited by
    #1

    Hi all, I have two DataGridViews on my form with similar data in each. I'd like to view the same section of both DataGridViews at the same time. In other words, if the scroll bars in one DataGridView is scrolled, I want to set the scroll bars for the other one accordingly. I found this article which explains how to set scroll bars (using Interop) but I'm either doing something wrong or it's just not working for DataGridViews: How to change scrollbars position in a multiline textbox[^] Based on the referenced article, this is block of code I currently have in the Scroll() event handler for but it does nothing:

    int orientation = 0;
    switch (e.ScrollOrientation)
    {
    case ScrollOrientation.HorizontalScroll: orientation = 0; break;
    case ScrollOrientation.VerticalScroll: orientation = 1; break;
    }
    SetScrollPos(dataGridView2.Handle, orientation, e.NewValue, true);
    SendMessage(dataGridView2.Handle, EM_LINESCROLL, 0, e.NewValue);

    Could anyone help me out here please?

    L B 2 Replies Last reply
    0
    • D Dewald

      Hi all, I have two DataGridViews on my form with similar data in each. I'd like to view the same section of both DataGridViews at the same time. In other words, if the scroll bars in one DataGridView is scrolled, I want to set the scroll bars for the other one accordingly. I found this article which explains how to set scroll bars (using Interop) but I'm either doing something wrong or it's just not working for DataGridViews: How to change scrollbars position in a multiline textbox[^] Based on the referenced article, this is block of code I currently have in the Scroll() event handler for but it does nothing:

      int orientation = 0;
      switch (e.ScrollOrientation)
      {
      case ScrollOrientation.HorizontalScroll: orientation = 0; break;
      case ScrollOrientation.VerticalScroll: orientation = 1; break;
      }
      SetScrollPos(dataGridView2.Handle, orientation, e.NewValue, true);
      SendMessage(dataGridView2.Handle, EM_LINESCROLL, 0, e.NewValue);

      Could anyone help me out here please?

      L Offline
      L Offline
      Luc Pattyn
      wrote on last edited by
      #2

      Hi, I haven't done this, however: 1. EM_LINESCROLL seems appropriate for a line-oriented Control, not for a Row/Column/Cell-oriented one. Not sure what would fit better. 2. I would try first without native code. I suggest you look into the Scroll event and the FirstDisplayedCell, FirstDisplayedScrollingRowIndex, FirstDisplayedScrollingColumnIndex properties. You could get the row/column indexes from the one DGV and use those in scrolling the other DGV. :)

      Luc Pattyn [My Articles] Nil Volentibus Arduum

      D 1 Reply Last reply
      0
      • D Dewald

        Hi all, I have two DataGridViews on my form with similar data in each. I'd like to view the same section of both DataGridViews at the same time. In other words, if the scroll bars in one DataGridView is scrolled, I want to set the scroll bars for the other one accordingly. I found this article which explains how to set scroll bars (using Interop) but I'm either doing something wrong or it's just not working for DataGridViews: How to change scrollbars position in a multiline textbox[^] Based on the referenced article, this is block of code I currently have in the Scroll() event handler for but it does nothing:

        int orientation = 0;
        switch (e.ScrollOrientation)
        {
        case ScrollOrientation.HorizontalScroll: orientation = 0; break;
        case ScrollOrientation.VerticalScroll: orientation = 1; break;
        }
        SetScrollPos(dataGridView2.Handle, orientation, e.NewValue, true);
        SendMessage(dataGridView2.Handle, EM_LINESCROLL, 0, e.NewValue);

        Could anyone help me out here please?

        B Offline
        B Offline
        BobJanova
        wrote on last edited by
        #3

        Have you tried: inheriting from DataGridView (gives you access to VerticalScrollBar), and putting some sort of synchronisation on your class?

        class MyGrid : DataGridView {
        public static void Link(IEnumerable<MyGrid> grids){
        foreach(MyGrid grid in grids)
        grid.VerticalScrollBar.Scroll += (s,e) => HandleScroll(grids, e.NewValue);

        }

        static void HandleScroll(IEnumerable<MyGrid> grids, int value){
        foreach(MyGrid grid in grids) grid.VerticalScrollBar.Value = value;
        }
        }

        And call it like:

        var grids = List<MyGrid>();
        grids.Add(myFirstGrid);
        grids.Add(mySecondGrid);

        MyGrid.Link(grids);

        ... in your form's initialisation process. (Note: I haven't tried this, just going on the documentation.) Ed: I tried, and you do have to have the lists as type MyGrid, not DataGridView. So you will have to make the controls on your form MyGrids, too. Also, you might want to handle DataGridView.Scroll as well as the scrollbar's Scroll; I'm not sure when each one gets fired.

        D 1 Reply Last reply
        0
        • L Luc Pattyn

          Hi, I haven't done this, however: 1. EM_LINESCROLL seems appropriate for a line-oriented Control, not for a Row/Column/Cell-oriented one. Not sure what would fit better. 2. I would try first without native code. I suggest you look into the Scroll event and the FirstDisplayedCell, FirstDisplayedScrollingRowIndex, FirstDisplayedScrollingColumnIndex properties. You could get the row/column indexes from the one DGV and use those in scrolling the other DGV. :)

          Luc Pattyn [My Articles] Nil Volentibus Arduum

          D Offline
          D Offline
          Dewald
          wrote on last edited by
          #4

          Thanks, but no, it doesn't quite solve my problem. 1. Yes, I also wondered about EM_LINESCROLL and I also wasn't sure what else to use or even how to go about finding out. 2. I know of the FirstDisplayedCell, FirstDisplayedScrollingRowIndex and FirstDisplayedScrollingColumnIndex properties but they only scroll the DataGridView to integral positions that coincide with the start of the referenced cell, row or column. Thanks though.

          1 Reply Last reply
          0
          • B BobJanova

            Have you tried: inheriting from DataGridView (gives you access to VerticalScrollBar), and putting some sort of synchronisation on your class?

            class MyGrid : DataGridView {
            public static void Link(IEnumerable<MyGrid> grids){
            foreach(MyGrid grid in grids)
            grid.VerticalScrollBar.Scroll += (s,e) => HandleScroll(grids, e.NewValue);

            }

            static void HandleScroll(IEnumerable<MyGrid> grids, int value){
            foreach(MyGrid grid in grids) grid.VerticalScrollBar.Value = value;
            }
            }

            And call it like:

            var grids = List<MyGrid>();
            grids.Add(myFirstGrid);
            grids.Add(mySecondGrid);

            MyGrid.Link(grids);

            ... in your form's initialisation process. (Note: I haven't tried this, just going on the documentation.) Ed: I tried, and you do have to have the lists as type MyGrid, not DataGridView. So you will have to make the controls on your form MyGrids, too. Also, you might want to handle DataGridView.Scroll as well as the scrollbar's Scroll; I'm not sure when each one gets fired.

            D Offline
            D Offline
            Dewald
            wrote on last edited by
            #5

            What a beautiful solution, thanks. It doesn't work 100% though. It only synchronises the scrollbars but not the actual position of the grid inside the gridview. Any idea why that would be? It seems that by setting MyGrid.VerticalScrollBar.Value, it only updates the position of the scrollbar but does nothing to the body of the grid.

            B 1 Reply Last reply
            0
            • D Dewald

              What a beautiful solution, thanks. It doesn't work 100% though. It only synchronises the scrollbars but not the actual position of the grid inside the gridview. Any idea why that would be? It seems that by setting MyGrid.VerticalScrollBar.Value, it only updates the position of the scrollbar but does nothing to the body of the grid.

              B Offline
              B Offline
              BobJanova
              wrote on last edited by
              #6

              Ah damn, I thought that setting Value would make the grid scroll. I guess it is hooked to the Scroll property and I don't see any way of externally forcing a scrollbar to fire that. You could probably send it a WM_SCROLL but if you need to resort to P/Invoke then you might as well do that directly on the grid – I'm trying to turn up a managed solution. Another thing you can try using the same protected-uncovering hackery is to call grid.OnScroll (with a ScrollEventArgs preset to the offset you want). But I suspect all that will do is fire the DGV.Scroll event and not actually cause the visible region to change. You might have to resort to synchronising rows with FirstDisplayedRow, which isn't ideal.

              D 1 Reply Last reply
              0
              • B BobJanova

                Ah damn, I thought that setting Value would make the grid scroll. I guess it is hooked to the Scroll property and I don't see any way of externally forcing a scrollbar to fire that. You could probably send it a WM_SCROLL but if you need to resort to P/Invoke then you might as well do that directly on the grid – I'm trying to turn up a managed solution. Another thing you can try using the same protected-uncovering hackery is to call grid.OnScroll (with a ScrollEventArgs preset to the offset you want). But I suspect all that will do is fire the DGV.Scroll event and not actually cause the visible region to change. You might have to resort to synchronising rows with FirstDisplayedRow, which isn't ideal.

                D Offline
                D Offline
                Dewald
                wrote on last edited by
                #7

                Yes, I'm pretty sure calling OnScroll will just fire the event but not update the actual gridview client area. I wouldn't mind resorting to synchronising the two grids based on FirstDisplayedScrollingRowIndex and FirstDisplayedScrollingColumnIndex if I had a way of forcing the grid to only scroll horizontally to integral values. In fact, for vertical scrolling, this method of syncing the two grids works perfectly. It's the horizontal scrolling that's a problem because the grid of which the scrollbar is moved can be scrolled to a position where it starts on a partial column, yet the linked grid will be scrolled to the start of that column. Do you know if there is a way I could enforce horizontal scrolling to also be limited to integral positions as is the case with vertical scrolling?

                B 1 Reply Last reply
                0
                • D Dewald

                  Yes, I'm pretty sure calling OnScroll will just fire the event but not update the actual gridview client area. I wouldn't mind resorting to synchronising the two grids based on FirstDisplayedScrollingRowIndex and FirstDisplayedScrollingColumnIndex if I had a way of forcing the grid to only scroll horizontally to integral values. In fact, for vertical scrolling, this method of syncing the two grids works perfectly. It's the horizontal scrolling that's a problem because the grid of which the scrollbar is moved can be scrolled to a position where it starts on a partial column, yet the linked grid will be scrolled to the start of that column. Do you know if there is a way I could enforce horizontal scrolling to also be limited to integral positions as is the case with vertical scrolling?

                  B Offline
                  B Offline
                  BobJanova
                  wrote on last edited by
                  #8

                  According to the documentation, DataGridView.HorizontalScrollOffset[^] is read/write. So you should be able to synchronise that without even needing to inherit from the DGV, as it's a public property. Why the vertical equivalent is read-only I don't understand. But that should work for horizontal scrolling (as long as you don't allow the user to mess with the column widths).

                  D 1 Reply Last reply
                  0
                  • B BobJanova

                    According to the documentation, DataGridView.HorizontalScrollOffset[^] is read/write. So you should be able to synchronise that without even needing to inherit from the DGV, as it's a public property. Why the vertical equivalent is read-only I don't understand. But that should work for horizontal scrolling (as long as you don't allow the user to mess with the column widths).

                    D Offline
                    D Offline
                    Dewald
                    wrote on last edited by
                    #9

                    Excellent. Thanks for the help. That is exactly what I was looking for.

                    1 Reply Last reply
                    0
                    Reply
                    • Reply as topic
                    Log in to reply
                    • Oldest to Newest
                    • Newest to Oldest
                    • Most Votes


                    • Login

                    • Don't have an account? Register

                    • Login or register to search.
                    • First post
                      Last post
                    0
                    • Categories
                    • Recent
                    • Tags
                    • Popular
                    • World
                    • Users
                    • Groups