How to freeze grid column in ScrollViewer or achieve something similar to that?

Emon Haque 3,176 Reputation points
2021-09-02T05:53:59.323+00:00

Here's what I've tried first:

128507-test1.gif

Cells of the leftmost column get same height as other row cell since they all belong to the same Grid BUT when I scroll to the right the left most column gets hidden eventually. I want that column to stay on the left always like the freeze pane of Excel. Is it possible with a single Grid?

Here I've tried with two Grid:

128400-test3.gif

BUT I couldn't fix the row height problem in the left grid. Tried to bind the Grid.Height and RowDefinition.Height of the left grid to those of the grid inside the ScrollViewer on the right BUT that didn't work. You can have these in the MainWindow.xaml:

<Grid x:Name="main">  
    <Grid.ColumnDefinitions>  
        <ColumnDefinition Width="auto"/>  
        <ColumnDefinition/>  
    </Grid.ColumnDefinitions>  
    <ScrollViewer x:Name="scr"   
                  Grid.Column="1"  
                  VerticalScrollBarVisibility="Auto"  
                  HorizontalScrollBarVisibility="Auto"/>  
</Grid>  

and these in MainWindow.xaml.cs:

public partial class MainWindow : Window  
{  
    public MainWindow() {  
        InitializeComponent();  
        var sideGrid = new Grid() { ShowGridLines = true };  
        var scrollGrid = new Grid() { ShowGridLines = true };  
        //sideGrid.SetBinding(Grid.HeightProperty, new Binding("ActualHeight") { Source = scrollGrid, Mode = BindingMode.OneWay });  
        for (int i = 0; i < 9; i++) {  
            var rf1 = new RowDefinition();  
            var rf2 = new RowDefinition();  
            scrollGrid.RowDefinitions.Add(rf1);  
            sideGrid.RowDefinitions.Add(rf2);  
            //rf2.SetBinding(RowDefinition.HeightProperty, new Binding("ActualHeight") { Source = rf1, Mode = BindingMode.OneWay });  
            scrollGrid.ColumnDefinitions.Add(new ColumnDefinition());  
        }  
        for (int i = 0; i < 9; i++)  
            scrollGrid.ColumnDefinitions.Add(new ColumnDefinition());  
        for (int i = 1; i < 9; i++) {  
            var sideText = new TextBlock() {  
                Text = "Row " + i,   
                Margin = new Thickness(0, 0, 20, 0),  
                VerticalAlignment = VerticalAlignment.Center  
            };  
            Grid.SetRow(sideText, i);  
            sideGrid.Children.Add(sideText);  
        }  
        main.Children.Add(sideGrid);  
        for (int i = 0; i < 19; i++) {  
            var headBlock = new TextBlock() {  
                Text = "Form " + i,  
                FontSize = 20,  
                HorizontalAlignment = HorizontalAlignment.Center,  
                VerticalAlignment = VerticalAlignment.Center  
            };  
            Grid.SetColumn(headBlock, i);  
            scrollGrid.Children.Add(headBlock);  
            for (int j = 1; j < 9; j++) {  
                var content = new TextBlock() {  
                    Text = $"Row {j} Column {i}",  
                    FontSize = 20,  
                    HorizontalAlignment = HorizontalAlignment.Center,  
                    VerticalAlignment = VerticalAlignment.Center,  
                    Margin = new Thickness(10, 0, 10, 0)  

                };  
                Grid.SetColumn(content, i);  
                Grid.SetRow(content, j);  
                scrollGrid.Children.Add(content);  
            }  
        }  
        scr.Content = scrollGrid;  
    }  
}  

for testing. One more thing How to hide the grid lines on cell that spans multiple Row/Colum?

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,716 questions
{count} votes

Accepted answer
  1. Emon Haque 3,176 Reputation points
    2021-09-06T03:20:10.557+00:00

    With 3 ScrollvVewer it's perfect. Now I've these in MainWindow.xaml.cs:

    public partial class MainWindow : Window  
    {  
        Grid topGrid, sideGrid, mainGrid;  
        public MainWindow() {  
            InitializeComponent();  
            generateMainGrid();  
            generateSideGid();  
            generateTopGrid();  
        }  
        void generateMainGrid() {  
            mainGrid = new Grid() { ShowGridLines = true };  
            for (int i = 0; i < 40; i++) {  
                mainGrid.RowDefinitions.Add(new RowDefinition() { SharedSizeGroup = "row" + i});  
                mainGrid.ColumnDefinitions.Add(new ColumnDefinition() { SharedSizeGroup = "col" + i });  
                var rect = new Border() { Name = "rect" + i };  
                Grid.SetColumn(rect, i);  
                mainGrid.Children.Add(rect);  
            }  
            for (int i = 0; i < 20; i++) {  
                for (int j = 0; j < 10; j++) {  
                    var block = new TextBlock() {   
                        Text = "Text " + i + " " + j, FontSize = 25,  
                        HorizontalAlignment = HorizontalAlignment.Center,  
                        VerticalAlignment = VerticalAlignment.Center  
                    };  
                    Grid.SetRow(block, i);  
                    Grid.SetColumn(block, j);  
                    mainGrid.Children.Add(block);  
                }  
            }  
            mainScroll.Content = mainGrid;  
        }  
        void generateSideGid() {  
            sideGrid = new Grid() { ShowGridLines = true };  
            for (int i = 0; i < 20; i++) {  
                sideGrid.RowDefinitions.Add(new RowDefinition() { SharedSizeGroup = "row" + i});  
                var block = new TextBlock() { Text = "Row " + "\n" + i, FontSize = 25 };  
                Grid.SetRow(block, i);  
                sideGrid.Children.Add(block);  
            }  
            sideScroll.Margin = new Thickness(0, 0, 0, SystemParameters.HorizontalScrollBarHeight);  
            sideScroll.Content = sideGrid;  
        }  
        void generateTopGrid() {  
            topGrid = new Grid() { ShowGridLines = true };  
            for (int i = 0; i < 10; i++) {  
                var cd = new ColumnDefinition() { SharedSizeGroup = "col" + i};  
                topGrid.ColumnDefinitions.Add(cd);  
                var block = new TextBlock() {   
                    Text = "Col " + i, FontSize = 25,  
                    HorizontalAlignment = HorizontalAlignment.Center  
                };  
                Grid.SetColumn(block, i);  
                topGrid.Children.Add(block);  
            }  
            topScroll.Margin = new Thickness(0, 0, SystemParameters.VerticalScrollBarWidth, 0);  
            topScroll.Content = topGrid;  
        }  
        void mainScrollChanged(object sender, ScrollChangedEventArgs e) {  
            sideScroll.ScrollToVerticalOffset(e.VerticalOffset);  
            topScroll.ScrollToHorizontalOffset(e.HorizontalOffset);  
        }  
    }  
    

    and these in MainWindow.xaml:

    <Grid Grid.IsSharedSizeScope="True">  
        <Grid.RowDefinitions>  
            <RowDefinition Height="auto"/>  
            <RowDefinition />  
        </Grid.RowDefinitions>  
        <Grid.ColumnDefinitions>  
            <ColumnDefinition Width="Auto"/>  
            <ColumnDefinition/>  
        </Grid.ColumnDefinitions>  
        <ScrollViewer x:Name="topScroll"  
                      Grid.Column="1"  
                      VerticalScrollBarVisibility="Hidden"  
                      HorizontalScrollBarVisibility="Hidden"/>  
        <ScrollViewer x:Name="sideScroll"  
                      Grid.Row="1"  
                      VerticalScrollBarVisibility="Hidden"  
                      HorizontalScrollBarVisibility="Hidden"/>  
        <ScrollViewer x:Name="mainScroll"  
                      Grid.Row="1"  
                      Grid.Column="1"  
                      VerticalScrollBarVisibility="Auto"  
                      HorizontalScrollBarVisibility="Auto"  
                      ScrollChanged="mainScrollChanged"/>  
    </Grid>  
    

    and this is what I get:

    129357-x1.gif

    0 comments No comments

2 additional answers

Sort by: Most helpful
  1. Hui Liu-MSFT 47,421 Reputation points Microsoft Vendor
    2021-09-03T09:20:38.263+00:00

    Based on my search, it is difficult to remove or hide the grid line in the columnspan. You could try to add a new grid in the first column of the scrollGrid with a span of 8.
    The code of xaml:

    <Grid  x:Name="main">  
            <Grid.ColumnDefinitions>  
                <ColumnDefinition/>  
            </Grid.ColumnDefinitions>  
            <ScrollViewer x:Name="scr"   
                       Grid.Column="1"  
                       VerticalScrollBarVisibility="Auto"  
                       HorizontalScrollBarVisibility="Auto"/>  
    </Grid>  
    

    The code of xaml.cs:

    public partial class MainWindow : Window  
      {  
        public MainWindow()  
        {  
          InitializeComponent();  
          var scrollGrid = new Grid() { ShowGridLines = true };  
    
          for (int i = 0; i < 9; i++)  
          {  
            var rf1 = new RowDefinition();  
            scrollGrid.RowDefinitions.Add(rf1);  
            scrollGrid.ColumnDefinitions.Add(new ColumnDefinition());  
          }  
          for (int i = 0; i < 9; i++)  
            scrollGrid.ColumnDefinitions.Add(new ColumnDefinition());  
    
    
          for (int i = 0; i < 10; i++)  
          {  
            var headBlock = new TextBlock()  
            {  
              Text = "Form " + i,  
              FontSize = 20,  
              HorizontalAlignment = HorizontalAlignment.Center,  
              VerticalAlignment = VerticalAlignment.Center  
            };  
            Grid.SetColumn(headBlock, i);  
            scrollGrid.Children.Add(headBlock);  
            for (int j = 1; j < 4; j++)  
            {  
              if (i == 1)  
              {  
                Grid subGird = new Grid() { ShowGridLines = true };  
                subGird.Background = Brushes.Red;  
                for (int k = 0; k < 2; k++)  
                {  
                  var rows = new RowDefinition();  
                  subGird.RowDefinitions.Add(rows);  
                  subGird.ColumnDefinitions.Add(new ColumnDefinition());  
                }  
                for (int m = 0; m< 2; m++)  
                  subGird.ColumnDefinitions.Add(new ColumnDefinition());  
                Grid.SetColumn(subGird, 1);  
                Grid.SetRow(subGird, 1);  
                Grid.SetRowSpan(subGird, 8);  
                scrollGrid.Children.Add(subGird);  
              }  
              else  
              {  
                var content = new TextBlock()  
                {  
                  Text = $"Row {j} Column {i}",  
                  FontSize = 20,  
                  HorizontalAlignment = HorizontalAlignment.Center,  
                  VerticalAlignment = VerticalAlignment.Center,  
                  Margin = new Thickness(10, 0, 10, 0)  
                };  
                Grid.SetColumn(content, i);  
                Grid.SetRow(content, j);  
                scrollGrid.Children.Add(content);  
              }  
    
            }  
          }  
          scr.Content = scrollGrid;  
        }  
      }  
    

    The picture of result:
    128996-y.png


    If the response is helpful, please click "Accept Answer" and upvote it. 
    Note: Please follow the steps in our [documentation][3] to enable e-mail notifications if you want to receive the related email notification for this thread. 

    [3]: https://learn.microsoft.com/en-us/answers/articles/67444/email-notifications.html

    1 person found this answer helpful.

  2. Emon Haque 3,176 Reputation points
    2021-09-02T17:21:41.003+00:00

    Here I've prepared two methods to get both:

    public partial class MainWindow : Window  
    {  
        public MainWindow() {  
            InitializeComponent();  
            getThingsInTwoGrid();  
            getThingsInASingleGrid();  
        }  
        void getThingsInTwoGrid() {  
            var sideGrid = new Grid() { ShowGridLines = true };  
            var scrollGrid = new Grid() { ShowGridLines = true };  
            //sideGrid.SetBinding(Grid.HeightProperty, new Binding("ActualHeight") { Source = scrollGrid, Mode = BindingMode.OneWay });  
            for (int i = 0; i < 10; i++) {  
                var rf1 = new RowDefinition();  
                var rf2 = new RowDefinition();  
                scrollGrid.RowDefinitions.Add(rf1);  
                sideGrid.RowDefinitions.Add(rf2);  
                //rf2.SetBinding(RowDefinition.HeightProperty, new Binding("ActualHeight") { Source = rf1, Mode = BindingMode.OneWay });  
                scrollGrid.ColumnDefinitions.Add(new ColumnDefinition());  
            }  
            for (int i = 0; i < 9; i++)  
                scrollGrid.ColumnDefinitions.Add(new ColumnDefinition());  
            for (int i = 2; i < 10; i++) {  
                var sideText = new TextBlock() {  
                    Text = "Row " + (i - 1),  
                    Margin = new Thickness(0, 0, 20, 0),  
                    VerticalAlignment = VerticalAlignment.Center  
                };  
                Grid.SetRow(sideText, i);  
                sideGrid.Children.Add(sideText);  
            }  
            main.Children.Add(sideGrid);  
            int colIndex = 0;  
            for (int i = 0; i < 15; i++) {  
                if (i == 0 || i == 13) {  
                    var headBlock = new TextBlock() {  
                        Text = "Form " + i,  
                        FontSize = 20,  
                        HorizontalAlignment = HorizontalAlignment.Center,  
                        VerticalAlignment = VerticalAlignment.Center  
                    };  
                    Grid.SetColumn(headBlock, colIndex);  
                    Grid.SetColumnSpan(headBlock, 3);  
                    scrollGrid.Children.Add(headBlock);  
                    for (int j = 1; j < 4; j++) {  
                        var subHeadBlock = new TextBlock() {  
                            Text = "Pattern " + j,  
                            FontSize = 15,  
                            HorizontalAlignment = HorizontalAlignment.Center,  
                            VerticalAlignment = VerticalAlignment.Center  
                        };  
                        Grid.SetColumn(subHeadBlock, colIndex);  
                        Grid.SetRow(subHeadBlock, 1);  
                        scrollGrid.Children.Add(subHeadBlock);  
                        for (int k = 2; k < 10; k++) {  
                            var content = new TextBlock() {  
                                Text = $"Row {j} Column {i}",  
                                FontSize = 20,  
                                HorizontalAlignment = HorizontalAlignment.Center,  
                                VerticalAlignment = VerticalAlignment.Center,  
                                Margin = new Thickness(10, 0, 10, 0)  
    
                            };  
                            Grid.SetColumn(content, colIndex);  
                            Grid.SetRow(content, k);  
                            scrollGrid.Children.Add(content);  
                        }  
                        colIndex++;  
                    }  
                }  
                else {  
                    var headBlock = new TextBlock() {  
                        Text = "Form " + i,  
                        FontSize = 20,  
                        HorizontalAlignment = HorizontalAlignment.Center,  
                        VerticalAlignment = VerticalAlignment.Center  
                    };  
                    Grid.SetColumn(headBlock, colIndex);  
                    Grid.SetRowSpan(headBlock, 2);  
                    scrollGrid.Children.Add(headBlock);  
                    for (int j = 2; j < 10; j++) {  
                        var content = new TextBlock() {  
                            Text = $"Row {j} Column {i}",  
                            FontSize = 20,  
                            HorizontalAlignment = HorizontalAlignment.Center,  
                            VerticalAlignment = VerticalAlignment.Center,  
                            Margin = new Thickness(10, 0, 10, 0)  
                        };  
                        Grid.SetColumn(content, colIndex);  
                        Grid.SetRow(content, j);  
                        scrollGrid.Children.Add(content);  
                    }  
                    colIndex++;  
                }  
            }  
            scr.Content = scrollGrid;  
        }  
        void getThingsInASingleGrid() {  
            var scrollGrid = new Grid() { ShowGridLines = true };  
            for (int i = 0; i < 10; i++) {  
                scrollGrid.RowDefinitions.Add(new RowDefinition());  
                scrollGrid.ColumnDefinitions.Add(new ColumnDefinition());  
            }  
            for (int i = 0; i < 10; i++)  
                scrollGrid.ColumnDefinitions.Add(new ColumnDefinition());  
            for (int i = 2; i < 10; i++) {  
                var sideText = new TextBlock() {  
                    Text = "Row " + (i - 1),  
                    Margin = new Thickness(0, 0, 20, 0),  
                    VerticalAlignment = VerticalAlignment.Center  
                };  
                Grid.SetRow(sideText, i);  
                scrollGrid.Children.Add(sideText);  
            }  
            int colIndex = 1;  
            for (int i = 0; i < 15; i++) {  
                if (i == 0 || i == 13) {  
                    var headBlock = new TextBlock() {  
                        Text = "Form " + i,  
                        FontSize = 20,  
                        HorizontalAlignment = HorizontalAlignment.Center,  
                        VerticalAlignment = VerticalAlignment.Center  
                    };  
                    Grid.SetColumn(headBlock, colIndex);  
                    Grid.SetColumnSpan(headBlock, 3);  
                    scrollGrid.Children.Add(headBlock);  
                    for (int j = 1; j < 4; j++) {  
                        var subHeadBlock = new TextBlock() {  
                            Text = "Pattern " + j,  
                            FontSize = 15,  
                            HorizontalAlignment = HorizontalAlignment.Center,  
                            VerticalAlignment = VerticalAlignment.Center  
                        };  
                        Grid.SetColumn(subHeadBlock, colIndex);  
                        Grid.SetRow(subHeadBlock, 1);  
                        scrollGrid.Children.Add(subHeadBlock);  
                        for (int k = 2; k < 10; k++) {  
                            var content = new TextBlock() {  
                                Text = $"Row {j} Column {i}",  
                                FontSize = 20,  
                                HorizontalAlignment = HorizontalAlignment.Center,  
                                VerticalAlignment = VerticalAlignment.Center,  
                                Margin = new Thickness(10, 0, 10, 0)  
    
                            };  
                            Grid.SetColumn(content, colIndex);  
                            Grid.SetRow(content, k);  
                            scrollGrid.Children.Add(content);  
                        }  
                        colIndex++;  
                    }  
                }  
                else {  
                    var headBlock = new TextBlock() {  
                        Text = "Form " + i,  
                        FontSize = 20,  
                        HorizontalAlignment = HorizontalAlignment.Center,  
                        VerticalAlignment = VerticalAlignment.Center  
                    };  
                    Grid.SetColumn(headBlock, colIndex);  
                    Grid.SetRowSpan(headBlock, 2);  
                    scrollGrid.Children.Add(headBlock);  
                    for (int j = 2; j < 10; j++) {  
                        var content = new TextBlock() {  
                            Text = $"Row {j} Column {i}",  
                            FontSize = 20,  
                            HorizontalAlignment = HorizontalAlignment.Center,  
                            VerticalAlignment = VerticalAlignment.Center,  
                            Margin = new Thickness(10, 0, 10, 0)  
                        };  
                        Grid.SetColumn(content, colIndex);  
                        Grid.SetRow(content, j);  
                        scrollGrid.Children.Add(content);  
                    }  
                    colIndex++;  
                }  
            }  
            scr.Content = scrollGrid;  
        }  
    }  
    

    You've to comment out one of these methods call and body when use the other. For getThingsInTwoGrid() you've to have these in MainWindow.xaml.cs:

    <Grid x:Name="main">  
        <Grid.ColumnDefinitions>  
            <ColumnDefinition Width="auto"/>  
            <ColumnDefinition/>  
        </Grid.ColumnDefinitions>  
        <ScrollViewer x:Name="scr"   
                      Grid.Column="1"  
                      VerticalScrollBarVisibility="Auto"  
                      HorizontalScrollBarVisibility="Auto"/>  
    </Grid>  
    

    and you'll get this:

    128851-test4.gif

    and for the getThingsInASingleGrid() have only the ScrollViewer like this:

    <!--<Grid x:Name="main">  
        <Grid.ColumnDefinitions>  
            <ColumnDefinition Width="auto"/>  
            <ColumnDefinition/>  
        </Grid.ColumnDefinitions>-->  
        <ScrollViewer x:Name="scr"   
                      Grid.Column="1"  
                      VerticalScrollBarVisibility="Auto"  
                      HorizontalScrollBarVisibility="Auto"/>  
    <!--</Grid>-->  
    

    and you'll get this:

    128779-test5.gif

    EDIT
    ----

    Forgot to add RowSpan in Column heading when recording the screen. Added that part in the code so you'll see the grid line strikes through the column headings where that spans 2 rows when you launch the demo.

    0 comments No comments