Resolved ScrollViewer doesn't work with dynamically created content

wlf

Member
Joined
Apr 26, 2020
Messages
12
Programming Experience
Beginner
Hi, I have a dockPanel inside a scrollviewer.
In that dockpanel I create a lot of buttons, and what happens is that the scrollviewer doesnt react at all and new buttons just clip through the app.
(And when I resize the app they stay cropped).
I can't find any instructions on how to set that up properly.
 

Sheepings

Senior Programmer
Staff member
Joined
Sep 5, 2018
Messages
1,141
Location
UK
Programming Experience
10+
That order of controls works fine together. Show your Xaml, and only the relevant code that creates and initialises these new controls. A screenshot of the problem would also be welcomed if not a problem for you to provide...
 
  • Like
Reactions: wlf

wlf

Member
Joined
Apr 26, 2020
Messages
12
Programming Experience
Beginner
That order of controls works fine together. Show your Xaml, and only the relevant code that creates and initialises these new controls. A screenshot of the problem would also be welcomed if not a problem for you to provide...
XAML part:
       <ScrollViewer VerticalScrollBarVisibility="Auto">
            <DockPanel HorizontalAlignment="Left" Height="419" VerticalAlignment="Top" Width="134" LastChildFill="False">
               <Button x:Name="showDinner" Content="Dinner" Height="39" VerticalAlignment="Top" DockPanel.Dock="Top" Click="showDinner_Click"/>
                <StackPanel x:Name="dinnerPanel" Visibility="Collapsed" Height="auto" VerticalAlignment="Top" Width="134" HorizontalAlignment="Left" DockPanel.Dock="Top"/>
            </DockPanel>
        </ScrollViewer>
button creation:
                Button button = new Button();

                button.Content = title;
                button.Name = title;
                button.Click += (sender, e) => readRecipe(sender, e, title);
                breakfastPanel.Children.Add(button);
Capture.PNG
the scrollbar stays the same and next buttons clip through the window. Resizing the window doesn't change anything for the buttons, but before I create them and resize the window then the scrollbar allows me to scroll but only because the original controls don't fit.
 

Skydiver

Staff member
Joined
Apr 6, 2019
Messages
1,227
Location
Virginia Beach, VA
Programming Experience
10+
Ah, interesting.

As an aside, why are you doing things the old WinForms way by adding controls procedurally, and the old Win32 way of making controls hold your data? The way WPF is supposed to be used is that you use the MVVM pattern. So in this case you would add your a new item to an observable collection, and that collection is bound to the stack panel which populates its contents using an item template of buttons.
 

wlf

Member
Joined
Apr 26, 2020
Messages
12
Programming Experience
Beginner
I mean I've been learning c# for like a month now so I don't really know which way is WinForms and which WPF and what MVVM patter or collections actually are. I just did it the way I would do it in JavaScript, seemed the most straightforward approach. So there isn't really a reason that the scrollbar doesn't work (except for it not knowing what to do because I don't do things how it would expect me to)? Also I would be super thankful if you could point me in a direction of some tutorials/pages about doing those things the correct way.
 

Skydiver

Staff member
Joined
Apr 6, 2019
Messages
1,227
Location
Virginia Beach, VA
Programming Experience
10+
At this point I don't know why the stack panel is not letting the dockpanel that it needs to resize, and consequently the dockpanel is not telling the scrollviewer that it is resizing and therefore the scrollbar needs to be recomputed.
 

Sheepings

Senior Programmer
Staff member
Joined
Sep 5, 2018
Messages
1,141
Location
UK
Programming Experience
10+
It looks like you are trying to create something like this :

Screenshot_129.jpg

I don't have a lot of free time at the moment, but if you have any questions, I will reply when i get a chance. Basically using the Grid and using the column span, you can move across sections of the grid where you have defined Grid.Row/Column definitions. Check out my brief example below. It might give you a better direction :
C#:
    <Grid x:Name="MainGrid" Margin="10,10,10,10">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="30*"/>
            <ColumnDefinition Width="80*"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="30"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <Grid Grid.Column="0" Width="180"  Grid.Row="0" Margin="0,10,557,9" Grid.ColumnSpan="2" Grid.RowSpan="2">
            <Grid.Background>
                <SolidColorBrush Color="Beige"/>
            </Grid.Background>
            <Rectangle Margin="10,10,10,10" Fill="WhiteSmoke" RadiusY="10" RadiusX="10" Width="162" Height="300">
                <Rectangle.Effect>
                    <DropShadowEffect BlurRadius="20" Color="#FFDEDEDE" RenderingBias="Quality" ShadowDepth="1"/>
                </Rectangle.Effect>
            </Rectangle>
          
            <ScrollViewer Height="270" Width="160" Name="leftBarScroll" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled">
                <StackPanel VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Width="80" Margin="30,30,30,30" Height="Auto">
                    <Button Content="b1"></Button>
                    <Button Content="b1"></Button>
                    <Button Content="b1"></Button>
                    <Button Content="b1"></Button>
                    <Button Content="b1"></Button>
                    <Button Content="b1"></Button>
                    <Button Content="b1"></Button>
                    <Button Content="b1"></Button>
                    <Button Content="b1"></Button>
                    <Button Content="b1"></Button>
                    <Button Content="b1"></Button>
                    <Button Content="b1"></Button>
                    <Button Content="b1"></Button>
                    <Button Content="b1"></Button>
                    <Button Content="b1"></Button>
                    <Button Content="b1"></Button>
                    <Button Content="b1"></Button>
                    <Button Content="b1"></Button>
                </StackPanel>
            </ScrollViewer>
        </Grid>
        <Grid Grid.Column="1" Grid.ColumnSpan="2" Background="Aqua">
          
        </Grid>
    </Grid>
I haven't put any comments in the source, but if you need to know something. Just quote the piece of code and I will get back to you next time I login.

Btw, kudos to you for using WPF and not Winforms. I like to see people are moving with the times.

Edit - Added cleaner xaml for the second column of the grid :
C#:
    <Grid x:Name="MainGrid" Margin="10,10,10,10">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="30*"/>
            <ColumnDefinition Width="80*"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <Grid Grid.Column="0" Width="180"  Grid.Row="0" Margin="0,10,557,9" Grid.ColumnSpan="2" Grid.RowSpan="2">
            <Grid.Background>
                <SolidColorBrush Color="Beige"/>
            </Grid.Background>
            <Rectangle Margin="10,10,10,10" Fill="WhiteSmoke" RadiusY="10" RadiusX="10" Width="162" Height="300">
                <Rectangle.Effect>
                    <DropShadowEffect BlurRadius="20" Color="#FFDEDEDE" RenderingBias="Quality" ShadowDepth="1"/>
                </Rectangle.Effect>
            </Rectangle>
           
            <ScrollViewer Height="270" Width="160" Name="leftBarScroll" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled">
                <StackPanel VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Width="80" Margin="30,30,30,30" Height="Auto">
                    <Button Content="b1"></Button>
                    <Button Content="b1"></Button>
                    <Button Content="b1"></Button>
                    <Button Content="b1"></Button>
                    <Button Content="b1"></Button>
                    <Button Content="b1"></Button>
                    <Button Content="b1"></Button>
                    <Button Content="b1"></Button>
                    <Button Content="b1"></Button>
                    <Button Content="b1"></Button>
                    <Button Content="b1"></Button>
                    <Button Content="b1"></Button>
                    <Button Content="b1"></Button>
                    <Button Content="b1"></Button>
                    <Button Content="b1"></Button>
                    <Button Content="b1"></Button>
                    <Button Content="b1"></Button>
                    <Button Content="b1"></Button>
                </StackPanel>
            </ScrollViewer>
        </Grid>
        <Grid Grid.Column="1" Grid.Row="0" Grid.RowSpan="1" Grid.ColumnSpan="2" Background="Aqua" Margin="10,10,10,10" Height="Auto">
           
        </Grid>
    </Grid>
 
Last edited:
  • Like
Reactions: wlf

wlf

Member
Joined
Apr 26, 2020
Messages
12
Programming Experience
Beginner
Okay so I have no idea how you fixed it but you did so thank you so much!
It had probably something to do with either:
putting it in a grid column,, which I did as well but it wasn't reflected in the code(?):
 <Grid Grid.Column="0" Width="180"  Grid.Row="0" Margin="0,10,557,9" Grid.ColumnSpan="2" Grid.RowSpan="2">
For the grid column, before I only snapped it to the grid in design window, so I thought that it worked but it wasn't reflected in the code so I'm not sure if it worked or not. I still don't really get why some changes in design window are reflected in XAML and some aren't.
putting scrollViewer on fixed height:
<ScrollViewer Height="270" Width="160">
ScrollViewer height I had on auto because I thought it needed to stretch(?), but now I see that it needs to be fixed like in your code so the scroll bar can work - because there is no more space.
setting height of my docking panel as auto:
<DockPanel VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Width="80" Margin="30,30,30,30" Height="Auto">
DockPanel's height I had fixed because I thought it would clip through the app (which it did either way) if I let it stretch as much as it wanted to. But now I understand that it should be allowed to stretch in height as much as it needs to because it's in a fixed height scrollViewer container which purpose is to let the user scroll the 'longer-than-app' panels.

Please, if you can, let me know if my assumptions as to why it worked this time are correct or not, thanks!
 

Sheepings

Senior Programmer
Staff member
Joined
Sep 5, 2018
Messages
1,141
Location
UK
Programming Experience
10+
Its kinda simple if you just read the xaml. Take the definitions for the Grid. The size of these items are imperative that you set the correct values here, because these will not resize if items in your grid or stackpanel are bigger in width or height than what is set here :
C#:
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="30*"/>
            <ColumnDefinition Width="80*"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
As you can see we have two columns and only one row. A row is from the top to the bottom. Columns are from left to right. So when we set the below definitions, we are adding two columns for the grid control :
C#:
            <ColumnDefinition Width="30*"/>
            <ColumnDefinition Width="80*"/>
C#:
                <Grid Grid.Column="0" Width="180"  Grid.Row="0" Margin="0,10,557,9" Grid.ColumnSpan="2" Grid.RowSpan="2">
Grid.ColumnSpan sets the number of columns that a child item can span. When using the grid control it is important to use columnspan too, because this allows us to control how many column items can reside in each one. Most people use other controls and use dockers to avoid having to manually do the extra legwork involved when using a grid layout like mine. But its worth writing the extra code! As you can see, you can use the grid control to achieve similar functionality. Anyway, the next bit opens up the option to set individual properties on this grid, since we are still operating inside of its closing tag </grid> :
C#:
            <Grid.Background>
                <SolidColorBrush Color="Beige"/>
            </Grid.Background>
Self explanatory, as it sets the background for this grid column and row, because they are both set to 0. Zero is the first column in the actual grid layout itself :
C#:
             Grid Grid.Column="0"
And the same applies for rows :
C#:
             Grid.Row="0"
If we changed these values to 1, it will move to set properties on the next ColumnDefinition/RowDefinition. (If we had additional Rows. We only have defined one.) Next I added a rectangle for style only, as it makes the UI look a bit more impressive especially with those radius corners curved :
C#:
            <Rectangle Margin="10,10,10,10" Fill="WhiteSmoke" RadiusY="10" RadiusX="10" Width="162" Height="300">
                <Rectangle.Effect>
                    <DropShadowEffect BlurRadius="20" Color="#FFDEDEDE" RenderingBias="Quality" ShadowDepth="1"/>
                </Rectangle.Effect>
            </Rectangle>
Next, while we are still in the same grid span of the first grid definition, we add the scrollviewer to this same ColumnDefinition :
C#:
                <ScrollViewer Height="270" Width="160" Name="leftBarScroll" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled">
And the important part here is the use of a StackPanel, and not a DockPanel which is used to Stack the child items of this panel on the item vertically :
C#:
                <StackPanel VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Width="80" Margin="30,30,30,30" Height="Auto">
Note that : VerticalAlignment="Stretch" HorizontalAlignment="Stretch" helps the child items to sit comfortably according to their own size. Then we add the buttons to this item. Finishing up, we have added the second Column Grid.ColumnDefinitions to the xaml :
C#:
        <Grid Grid.Column="1" Grid.Row="0" Grid.RowSpan="1" Grid.ColumnSpan="2" Background="Aqua" Margin="10,10,10,10" Height="Auto">

        </Grid>
Hope this helps you understand how it works. If you have any other questions, you will need to wait for one of the other guys to chip in. As I will be away for the next day or so. ;)
 
  • Like
Reactions: wlf

wlf

Member
Joined
Apr 26, 2020
Messages
12
Programming Experience
Beginner
Thanks so much! Now if someone could answer my previous question whether I was right about what fixed it for me? Thanks!
 

Sheepings

Senior Programmer
Staff member
Joined
Sep 5, 2018
Messages
1,141
Location
UK
Programming Experience
10+
The answers are in line 11, 21, 22. and have already been explained to you. You need to READ the explanation I already provided you.
ScrollViewer height I had on auto because I thought it needed to stretch(?)
It should be bound by bindings, and you can really only do that approperiatly using a MVVM approach. The scroll viewer should be set to a size that fits or matches it's parent.
But now I understand that it should be allowed to stretch in height as much as it needs to because it's in a fixed height scrollViewer container
The panel, (in this case) is a stack panel. And it is more appropriate than a dock panel. Because you're not trying to dock child items one after another, instead you want to stack them. And if you want to place spacing, then you need to add a margin for that.

Lastly, no the scroll viewer shouldn't be allowed to stretch as much as it wants, nor is there any option to let it anyway, not as far as I'm aware. However, it's the child control - the stack panel that needs to be able to stretch in height and width, as its the scroll viewer which will compensate for how much scrolling is required as the panel expands with the added child controls. ie your buttons which reside inside it which causes the panel to expand...

I don't have a lot of free time right now so I hope you get it. You should also know that all parent items of any child control will dictate the maximum height/width of all its child controls no matter what those child controls parameters are.
 

wlf

Member
Joined
Apr 26, 2020
Messages
12
Programming Experience
Beginner
You need to READ the explanation I already provided you.
You say that but then you don't really read what I wrote either. I said "because it's in a fixed height scrollViewer container " and you go off telling me how "no, scrollviewer shouldn't be allowed to stretch". Yes I know I just said that and only wanted confirmation. I was talking how the dockPanel should be allowed to stretch because the scrollviewer would compensate.
The answers are in line 11, 21, 22. and have already been explained to you.
No need to be rude, I literally asked about those lines and only wanted confirmation that what I realized was correct.
Thanks anyway.
 

Sheepings

Senior Programmer
Staff member
Joined
Sep 5, 2018
Messages
1,141
Location
UK
Programming Experience
10+
You say that but then you don't really read what I wrote either.
If I didn't read what you wrote, I wouldn't have replied highlighting that part to you. Would i? You need to do some research into the properties on MSDN Search. To re-quote :
Note that : VerticalAlignment="Stretch" HorizontalAlignment="Stretch" helps the child items to sit comfortably according to their own size.
Then you come back and ask me the same thing after me explaining what is happening in the xaml at that point. So let me elaborate regarding your question :
ScrollViewer height I had on auto because I thought it needed to stretch(?), but now I see that it needs to be fixed like in your code so the scroll bar can work - because there is no more space.
There are a number of factors to consider when setting the size of a control. These size settings depend on what properties you've set on parent controls. This should have been evident to you when I set the Grid Definitions with a star asterisk, unless you don't know what setting an asterisk does when placed after a value... Oh and also; to correct myself. The scroll viewer does have properties for setting vertical/horizontal alignment to stretch. But you would be best using min/max width/height if you plan on allowing the alignment properties to be set to stretch. So they can only stretch up until a min/max point in size. You might also find this helpful regarding why I set the Grid.ColumnDefinitions with * - See : Meaning of * (asterisk) in a WPF ColumnDefinition? - You can also avoid setting a height and width which is the equivalent to using fill in old Winforms. However, this can be overruled if a parent control of the scroll viewer has a fixed properties dimensions for both height and width. Then the scroll viewer will only size itself to its parent.

How does this jazz for a decent enough answer to your question?

I was talking how the dockPanel should be allowed to stretch because the scrollviewer would compensate.
If it hasn't dawned on you. I am not using a dock panel, as I am using a stack panel which has different characteristic behavior. And for the later part of your statement, yes that is true.

No need to be rude, I literally asked about those lines and only wanted confirmation that what I realized was correct.
Thanks anyway.
Lastly, I wasn't being rude. You haven't seen me be rude yet. So try not to read to much between the lines.

I was clearly pointing you back to the lines responsible for altering the behavior you are questioning. It doesn't take a scientist to change some of the values to experiment to see some of the different behaviors caused by setting alternative parameter values in the xaml. You should also note, that I no longer have that code in a project. So It's a hassle for me to go copy and pasting it from here just to test something new which you are more than capable of doing yourself. You should also note that I am not your paid tutor, nor am I hear to drip feed you information like a baby receiving his bottle. So lets not go throwing your toys out of the pram and accusing me of being rude, when I am not. I've been courteous to give you as much as I have.

You should also know that you are on a public self-help website. That means, you are required to help yourself. And any code contributions or examples provided to you on this board by any user are provided as a matter of generosity, and we are not obligated to give you any such examples either. It is further expected that you do your own research into what you were given before coming back and asking additional questions. A simple Google search for xaml asterisk shows helpful information which would have answered your question. We don't get paid for our contributions, and you should let it be noted that we don't always have the time to write replies explaining every little detail. That's why you have fingers and a search engine.
 

wlf

Member
Joined
Apr 26, 2020
Messages
12
Programming Experience
Beginner
Jesus Christ do you get off to this?
throwing your toys out
who the hell do you think you are?
You should also note that I am not your paid tutor, nor am I hear to drip feed you information like a baby receiving his bottle.
No one asked you to answer so stop crying about that. Talk about sitting on a high horse.
What every little detail? Anyone saying "yes" or "no" to my question would be fine. And if you read that question you would've given a short simple answer, especially since you're so "short on time".
You chose to write 50 sentences.
You haven't seen me be rude yet.
It doesn't take a scientist
I am not your paid tutor, nor am I hear to drip feed you
throwing your toys
Yea, this is not rude or passive aggressive at all. If you don't want to help - don't.
 

Sheepings

Senior Programmer
Staff member
Joined
Sep 5, 2018
Messages
1,141
Location
UK
Programming Experience
10+
The answers are in line 11, 21, 22. and have already been explained to you.
This is not being rude, this is telling you where to look for an answer to the question you asked which is evidently explained in the xaml. You then went on to accuse me of being rude which I was not :
No need to be rude, I literally asked about those lines and only wanted confirmation that what I realized was correct.
Thanks anyway.
Despite your accusations to be rude; I continued to further explain to you in more detail above, and now you come back nitpicking and spoiling for an argument. :LOL:
No one asked you to answer so stop crying about that. Talk about sitting on a high horse.
Now you're being rude. And I am not on any high horse. If I was, I would close your topic for derailing it with accolades of ranting remarks and accusations. Instead, I ask that you keep your topic about your issue and not about me or making irrelevant accusations.

This is how I always am. and tough shit if you don't like it. I've been nothing but polite to you until now. You are welcome to report the posts you feel are rude and an admin will view them for you when they get time. I will not be replying any further on this, so lets leave it there. Your topic will remain open unless you continue your shenanigans.

Actually, I answered you because you weren't getting replies from the other members. Probably because they expected you to do a little googling also. I was being courteous by replying. But I won't make that mistake in the future. ;)
 
Top Bottom