question

EmonHaque-1485 avatar image
0 Votes"
EmonHaque-1485 asked EmonHaque-1485 edited

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

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-wpf
test1.gif (1.8 MiB)
test3.gif (1.9 MiB)
· 2
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Hi,@ EmonHaque-1485. Usually we use your method to freeze grid columns in ScrollViewer . How do you define Pattern1, Pattern2 and Pattern3 in your Form1? Could you show me its code? I use your code and there is no grid lines in Form1.
128600-cd.png

0 Votes 0 ·
cd.png (58.1 KiB)

@HuiLiu-MSFT, posted the code for both approach in answer section.

0 Votes 0 ·
EmonHaque-1485 avatar image
0 Votes"
EmonHaque-1485 answered EmonHaque-1485 edited

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


x1.gif (1.3 MiB)
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

EmonHaque-1485 avatar image
0 Votes"
EmonHaque-1485 answered EmonHaque-1485 edited

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.


test4.gif (1.5 MiB)
test5.gif (1.8 MiB)
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

HuiLiu-MSFT avatar image
1 Vote"
HuiLiu-MSFT answered EmonHaque-1485 commented

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 to enable e-mail notifications if you want to receive the related email notification for this thread. 



y.png (41.8 KiB)
· 1
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

@HuiLiu-MSFT, that probably will solve the strikethrough issue. What about freezing the first column? The approach I've tried doesn't work! For example when I've vertical scrollbar, some of the rows in right grid are hidden BUT in the left grid I see all rows. When I maximise the window, row of those two grids are not aligned properly.

0 Votes 0 ·