WPF: How to make two panels share the same vertical scroll bar and each panel owns itself horizontal scroll bar?

Jane Chen - Applied BioCode 21 Reputation points
2020-07-06T23:55:11.637+00:00

We need to a create new WPF tool to compare two files.
This compare tool shows the contents of two files line by line and indicates the difference in the same line.
First we create two ListViews to display both source file and target file.
So each ListView has its own vertical scroll bar and horizontal scroll bar.
What we notice is that if we scroll vertical bar in left list view and right list view does not scroll. So the line numbers are off each other. That is not we want.
We nee to scroll vertical bar and both ListViews move together. So we always see the same line are aligned together.
Does anyone has a good suggestion what control we should use so two panels share the same vertical scroll bar and own its own horizontal scroll bar. Thx!

Windows Presentation Foundation
Windows Presentation Foundation
A part of the .NET Framework that provides a unified programming model for building line-of-business desktop applications on Windows.
2,784 questions
0 comments No comments
{count} votes

Accepted answer
  1. DaisyTian-1203 11,626 Reputation points
    2020-07-07T03:37:13.4+00:00

    You can use ScrollChanged event to implement the function:
    The cs code is:

     public MainWindow()  
            {  
                InitializeComponent();  
                initList();  
            }  
            public void initList()  
            {  
                List<Book> listBook = new List<Book>();  
                for (int i = 0; i < 30; i++)  
                {        
                    listBook.Add(new Book(){Num="00"+i.ToString(), Name="testBook"+i, Type="Math", Author="qiaobus"});                  
                }             
                listView1.ItemsSource = listBook;          
                listView2.ItemsSource = listBook;          
            }  
      
            ScrollViewer sv1, sv2;  
            private void Window_Loaded(object sender, RoutedEventArgs e)  
            {  
    
                sv1 = VisualTreeHelper.GetChild(VisualTreeHelper.GetChild(this.listView1, 0), 0) as ScrollViewer;  
                sv2 = VisualTreeHelper.GetChild(VisualTreeHelper.GetChild(this.listView2, 0), 0) as ScrollViewer;  
      
                sv1.ScrollChanged += new ScrollChangedEventHandler(sv1_ScrollChanged);  
                sv2.ScrollChanged += new ScrollChangedEventHandler(sv2_ScrollChanged);  
            }  
      
            void sv1_ScrollChanged(object sender, ScrollChangedEventArgs e)  
            {  
                sv2.ScrollToVerticalOffset(sv1.VerticalOffset);  
            }  
      
            void sv2_ScrollChanged(object sender, ScrollChangedEventArgs e)  
            {  
                sv2.ScrollToVerticalOffset(sv2.VerticalOffset);  
            }  
        }  
        public class Book  
        {  
           public string Num { get; set; }  
           public string Name { get; set; }  
           public string Type { get; set; }  
           public string Author { get; set; }  
        }  
    

    The xaml code is (add Window_Loaded for the window):

     <WrapPanel>  
                <ListView x:Name="listView1" Width="350" Height="400" ItemsSource="{Binding}" >  
                    <ListView.View>  
                        <GridView>  
                            <GridViewColumn Header="Num" Width="80" DisplayMemberBinding="{Binding Num}" />  
                            <GridViewColumn Header="Name" Width="80" DisplayMemberBinding="{Binding Name}"/>  
                            <GridViewColumn Header="Type" Width="80"  DisplayMemberBinding="{Binding Tyep}" />  
                            <GridViewColumn Header="Author" Width="80"  DisplayMemberBinding="{Binding Author}"/>  
                        </GridView>  
                    </ListView.View>  
                </ListView>  
                <ListView x:Name="listView2" Width="350" Height="400" ItemsSource="{Binding}" >  
                    <ListView.View>  
                        <GridView>  
                            <GridViewColumn Header="Num" Width="80" DisplayMemberBinding="{Binding Num}" />  
                            <GridViewColumn Header="Name" Width="80" DisplayMemberBinding="{Binding Name}"/>  
                            <GridViewColumn Header="Type" Width="80"  DisplayMemberBinding="{Binding Tyep}" />  
                            <GridViewColumn Header="Author" Width="80"  DisplayMemberBinding="{Binding Author}"/>  
                        </GridView>  
                    </ListView.View>  
                </ListView>  
            </WrapPanel>  
    

    The result picture is:

    11449-13.gif

    1 person found this answer helpful.
    0 comments No comments

1 additional answer

Sort by: Most helpful
  1. Jane Chen - Applied BioCode 21 Reputation points
    2020-07-07T06:17:11.413+00:00

    Daisy Tian,

    thanks for an excellent solution!
    -Jane


Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.