Question Can a wrap panels children be aligned with each other?

glasswizzard

Well-known member
Joined
Nov 22, 2019
Messages
126
Programming Experience
Beginner
I have a wrappanel with several labels the user can enable or disable (collapse or make visible). When it wraps around, the labels on the second row aren't aligned with the labels above (because they aren't the same length).
Is there a way to get them to align with each other, so their centers are lined up?
 
Do you really want a wrap panel, or a stack panel?
 
If enough labels are visible they will need to wrap around. I don't know how I would do that with a stack panel. Is it possible?
 
No, because the StackPanel doesn't wrap the content in the way that you want. Instead it stretches its content in one direction; that being horizontal or vertical. This allows you to stack items on top of another item within the stack.

The wrap panel will stack its child controls by wrapping them together, based on the best possible fit for each child control to fill the wrap panel adequately.

Neither of these are likely what you want. Since I don't fully know what you are doing, I won't advise on an alternative. Maybe you would be best initialising your controls positions manually?
 
The element.Margin being used from the framework in that Wrap Panel is all what is giving the spacing of the objects in that article... <Button Margin="5,5,5,5">Alpha</Button> Sure, I guess it could work, but you are still using the wrong control for the job IMO. The UniformWrapPanel inherits from a panel behind the scenes. Some of that code could be used with a simple panel instead; to inherit the same functionality.

If our op could explain what their goal is, maybe we could recommend a more fitting practical control. Based on the little info given, maybe it be best to use <Grid.ColumnDefinitions> and set the width to Auto and by setting a margin on your control in Xaml, you can set some "spacing" between your elements.
 
Thanks for the suggestions guys I'm getting closer and closer.

While I couldn't figure out how to use that custom panel, Sheepings does have a point, I don't think I need to use it. By setting a width and height for the stackpanels that are the children of my wrappanel I have them aligned nicely, it left just one small quirk. Here is a picture for a better idea of what I'm talking about:

Annotation 2020-01-06 161828.jpg


That whole thing is a wrappanel. It's children are stackpanels with two textblocks inside, a text textblock and a number textblock.

Everything is nice and gridlike but notice that on each row a zero is pushed out of horizontal alignment with the other zero's because of the title text. This could be solved by somehow getting those number textblocks to dock at the bottom while the text remains docked at the top so they don't interfere with each other. I tried replacing the stackpanels with dockpanels and setting each textblocks DockPanel.Dock to top and bottom as required and got this:

Annotation 2020-01-06 170001.jpg


It's not perfect, those spaces between those zeros and the one-line title text is a bit unpleasant.

What I'll try to do is replace the dockpanel/stackpanels with a two row grid giving each row 50% of the space creating an evenly halved area for each textblock. Maybe it'll work, I'll let you know. If you guys have any ideas I'm all ears.
 
That is not the suggestion i gave you. While I do admire your enthusiasm to learn about different controls, I don't admire that you use them incorrectly. Lets recap :
maybe it be best to use <Grid.ColumnDefinitions> and set the width to Auto and by setting a margin on your control in Xaml, you can set some "spacing" between your elements.
If you go onto MSDN and search for Grid.ColumnDefinitions you will see what I am suggesting. Had you already implemented as I suggested, you wouldn't need a wrap panel at all; least with numerous stack panels. That's a misuse of controls.
By setting a width and height for the stackpanels that are the children of my wrappanel I have them aligned nicely, it left just one small quirk.
Again, this is not what a stack panel is used for, as I've already explained to you above. I'll quote myself again in hope that you read what advice I am giving you. I said :
No, because the StackPanel doesn't wrap the content in the way that you want. Instead it stretches its content in one direction; that being horizontal or vertical. This allows you to stack items on top of another item within the stack.

The wrap panel will stack its child controls by wrapping them together, based on the best possible fit for each child control to fill the wrap panel adequately.
That being said; I wasn't trying to imply anywhere there that you use a number of stackpanels inside a wrap panel.
 
and by setting a margin on your control in Xaml
To be doubly clear, this was implying that you set a margin on your labels through your Xaml code, which will give you adequate spacing when your Coloums are being auto aligned to your Grid by using the Auto property when setting the width for each ColumnDefinitions.

If I am not being clear, you need to ask me a direct question. Otherwise if you understand what I am advising, you then need to turn to read the documentation for <Grid.ColumnDefinitions>.
 
C#:
    <Grid HorizontalAlignment="Left" Height="269" VerticalAlignment="Top" Width="509">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
        </Grid.ColumnDefinitions>
    </Grid>
Grid.ColumnDefinition is a sub fragment of the Grid Control. Time to get on to MSDN, and start reading up, because none of these panels you are using are needed for doing what you've provided in your screenshots. That is nothing a grid can't provide alone. ;)
 
I'm very confused :confused:

I can't understand how a grid could do what a wrappanel does. Maybe the mock up looks like a simple grid but as the user enables more textblocks I need them to fill in to the right and then wrap back around, also all the jumbling around that goes on when the window is resized. If you are saying a grid can do that then this is where my confusion lies. I have used the auto spacing for grid definitions and know how to use that (I think) but can't think of any way at all to do this with a grid.

That is not the suggestion i gave you.
I wasn't trying to imply anywhere there that you use a number of stackpanels inside a wrap panel.

I know, sorry for not being clear, the stackpanels were my original set up from the start. I used them to stack the two textblocks on top of each other. Currently I've replaced them with two-row grids with each ones height set to * to keep them proportionate.

If you go onto MSDN and search for Grid.ColumnDefinitions you will see what I am suggesting. Had you already implemented as I suggested, you wouldn't need a wrap panel at all; least with numerous stack panels. That's a misuse of controls.

I don't know how to implement it, I don't understand it at all. Sorry for being dense, I just don't get it. I've looked on MSDN at the Grid.ColumnDefinitions but nothing stands out to me as being what I need. From what I understand so far, the only thing that can do what I need is the wrappanel.

But I have managed to do it, by using specifically sized 2-row grids (to stack the two textblocks on top of each other) as the children of the wrappanel (with the appropriate margins) everything looks and behaves exactly as I want it to. Can it really be so wrong? ?
 
C#:
<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="WPFTestApp.Window1"
        Title="Window1" Width="Auto">
    <Grid Width="Auto" AutomationProperties.IsOffscreenBehavior="Onscreen">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="Auto" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <Label Margin="5,5,5,5" Content="Row AAAAA Column A" Grid.Row="0" Grid.Column="0" HorizontalAlignment="Center" VerticalAlignment="Center"></Label>
        <Label Margin="5,5,5,5" Content="Row A Column B" Grid.Row="0" Grid.Column="1" HorizontalAlignment="Center" VerticalAlignment="Center"></Label>
        <Label Margin="5,5,5,5" Content="Row A Column CCCCCCC" Grid.Row="0" Grid.Column="2" HorizontalAlignment="Center" VerticalAlignment="Center"></Label>
        <Label Margin="5,5,5,5" Content="Row B Column A" Grid.Row="1" Grid.Column="0" HorizontalAlignment="Center" VerticalAlignment="Center"></Label>
        <Label Margin="5,5,5,5" Content="Row B Column B" Grid.Row="1" Grid.Column="1" HorizontalAlignment="Center" VerticalAlignment="Center"></Label>
        <Label Margin="5,5,5,5" Content="Row B Column C" Grid.Row="1" Grid.Column="2" HorizontalAlignment="Center" VerticalAlignment="Center"></Label>
    </Grid>
</Window>
 
So you're trying to say that it's not possible with only a Grid? Nonsense. It's not perfect, and you do need to tweak it.

Your current problem is your lack of experience with Xaml code. But don't take that as me judging you, as I'm not. I admire your willingness to buy a book on WPF alone, then to further teach yourself, by dabbling with the various controls to try and achieve a very simple task. That's actually rude of me, since any task is easy when you know how to approach it. Whereas; in my case, I've spent the better part of my later career and life learning as much WPF as I could. So, this is actually all very boring for me, as it is only basic Xaml, and basic structuring. Of course, you're only partly there, since you have yet to write your code for the various layout to be altered when your user decides to do his clicky thing and add more controls, and for each control, you need more <Grid.ColumnDefinitions> and <Grid.RowDefinitions>, and once they are created, you would add more labels etc. It's not something I will be doing for you, as its time consuming, and time I'd rather not waste doing it for you. It's a learning experience for you too, so play with what I gave you.

Have a good night.
 
@glasswizzard :
In your screenshots in post #7, you had some items which have two lines of text. Is the two lines of text intentional, or are they the result of a long line of text that gets line wrapped to two lines because you've setup a specific width for each item?
Are widths of all the items the same?
If they are all the same, is that something you hardcoded, or is it computed somehow?
If they are not all the same, is there a maximum width? Is that maximum width something you hardcoded, or is it computed somehow?
If they are not all the same, are narrow items supposed to center up below the wider ones?
For the two line line wrapped items, did you decide on whether you wanted the text flush to the top, flush to the bottom just above the number, or centered between the top and the number?
 
So you're trying to say that it's not possible with only a Grid?

I wasn't trying to state it as a fact, I just meant that I can't understand at all how it could be done, I'm specifically talking about the "wrapping", with a wrappanel it's obvious and simple, with a grid I'm still at a total loss, even with the help you've given so far (I'm beginning to feel like I'm being annoying by not getting this). If I imagine attempting what you describe, I have my textblocks (I've been calling them labels this whole time) each set to their appropriate row/column, this is brick wall I can't get passed, they would have to move, how could they ever move to a different cell?

Your current problem is your lack of experience with Xaml code. But don't take that as me judging you, as I'm not. I admire your willingness to buy a book on WPF alone, then to further teach yourself, by dabbling with the various controls to try and achieve a very simple task. That's actually rude of me, since any task is easy when you know how to approach it. Whereas; in my case, I've spent the better part of my later career and life learning as much WPF as I could. So, this is actually all very boring for me, as it is only basic Xaml, and basic structuring. Of course, you're only partly there, since you have yet to write your code for the various layout to be altered when your user decides to do his clicky thing and add more controls, and for each control, you need more <Grid.ColumnDefinitions> and <Grid.RowDefinitions>, and once they are created, you would add more labels etc. It's not something I will be doing for you, as its time consuming, and time I'd rather not waste doing it for you. It's a learning experience for you too, so play with what I gave you.

Have a good night.

When people are teaching me things I never take anything personally or as a judgement, I know I'm failing at the most basic things, and self learning is a struggle. I'm just grateful for any time given to trying to help this floundering noob.

I looked at the code you posted and ran it in VS. I understand what you've written, I just don't see how any wrapping could come of it since it's in a grid. I'm not trying to say that you're wrong, obviously you're the one who knows, not me, it's just that unless I see a grid do that or something I don't know if I can believe it. In your code there are three columns, how much more code do you think it would take to get those columns to wrap if the window size is reduced enough? Can you give me some hints on that one specific aspect, it's the only thing I'm not understanding, the wrapping part.

This is the one and only time I've come across something that I can't begin to even try to attempt. I feel like there is some key piece of information I'm missing that is making this seem absolutely impossible to such an extent It makes me wonder if I've been unclear and given you a false impression of what I'm going for. So, just to make sure and be absolutely crystal clear would you mind pasting the code below into your IDE, running the app and confirming that the behaviour you see when resizing the window can be done with a grid alone, if so, it makes me wonder why the wrappanel would ever be used over the grid (well, it's easier for us noobs I guess).

XML:
<Window x:Class="WpfApp1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp1"
mc:Ignorable="d"
Title="MainWindow" Width="510" Height="300" Background="#FF191919" Foreground="LightSlateGray" WindowStartupLocation="CenterScreen" >
       
        <WrapPanel  Grid.Row="3"
Grid.Column="1"
Grid.ColumnSpan="3"
                    HorizontalAlignment="Center">
           
<Grid Height="75" Width="100">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock VerticalAlignment="Center" TextAlignment="Center" TextWrapping="Wrap" Text="LoremIpsum" TextDecorations="Underline" HorizontalAlignment="Center" FontSize="14" FontFamily="Georgia"/>
<TextBlock Grid.Row="1" VerticalAlignment="Center" Text="0" HorizontalAlignment="Center" FontSize="28"/>
            </Grid>
            <Grid  Height="75" Width="100">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock VerticalAlignment="Center" TextAlignment="Center" TextWrapping="Wrap" Text="LoremIpsum" TextDecorations="Underline" HorizontalAlignment="Center" FontSize="14" FontFamily="Georgia"/>
<TextBlock Grid.Row="1" VerticalAlignment="Center" Text="0" HorizontalAlignment="Center" FontSize="28" />
            </Grid>
            <Grid  Height="75" Width="100">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock VerticalAlignment="Center" TextAlignment="Center" TextWrapping="Wrap" Text="LoremIpsum" TextDecorations="Underline" HorizontalAlignment="Center" FontSize="14" FontFamily="Georgia"/>
<TextBlock Grid.Row="1" VerticalAlignment="Center" Text="0" HorizontalAlignment="Center" FontSize="28"/>
            </Grid>
            <Grid  Height="75" Width="100">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock VerticalAlignment="Center" TextAlignment="Center" TextWrapping="Wrap" Text="LoremIpsum Lorem" TextDecorations="Underline" HorizontalAlignment="Center" FontSize="14" FontFamily="Georgia"/>
<TextBlock Grid.Row="1" VerticalAlignment="Center" Text="0" HorizontalAlignment="Center" FontSize="28"/>
            </Grid>
           
<Grid Margin="0 5" Height="75" Width="100">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock VerticalAlignment="Center" TextAlignment="Center" TextWrapping="Wrap" Text="LoremIpsum" TextDecorations="Underline" HorizontalAlignment="Center" FontSize="14" FontFamily="Georgia"/>
<TextBlock Grid.Row="1" VerticalAlignment="Center" Text="0" HorizontalAlignment="Center" FontSize="28"/>
            </Grid>
            <Grid Margin="0 5" Height="75" Width="100">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock VerticalAlignment="Center" TextAlignment="Center" TextWrapping="Wrap" Text="LoremIpsum Lorem" TextDecorations="Underline" HorizontalAlignment="Center" FontSize="14" FontFamily="Georgia"/>
<TextBlock Grid.Row="1" VerticalAlignment="Center" Text="0" HorizontalAlignment="Center" FontSize="28"/>
            </Grid>
            <Grid Margin="0 5" Height="75" Width="100">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock VerticalAlignment="Center" TextAlignment="Center" TextWrapping="Wrap" Text="LoremIpsum Lorem" TextDecorations="Underline" HorizontalAlignment="Center" FontSize="14" FontFamily="Georgia"/>
<TextBlock Grid.Row="1" VerticalAlignment="Center" Text="0" HorizontalAlignment="Center" FontSize="28"/>
            </Grid>
            <Grid Margin="0 5" Height="75" Width="100">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock VerticalAlignment="Center" TextAlignment="Center" TextWrapping="Wrap" Text="LoremIpsum Lorem" TextDecorations="Underline" HorizontalAlignment="Center" FontSize="14" FontFamily="Georgia"/>
<TextBlock Grid.Row="1" VerticalAlignment="Center" Text="0" HorizontalAlignment="Center" FontSize="28"/>
            </Grid>
            <Grid Margin="0 5" Height="75" Width="100">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock VerticalAlignment="Center" TextAlignment="Center" TextWrapping="Wrap" Text="LoremIpsum Lorem" TextDecorations="Underline" HorizontalAlignment="Center" FontSize="14" FontFamily="Georgia"/>
<TextBlock Grid.Row="1" VerticalAlignment="Center" Text="0" HorizontalAlignment="Center" FontSize="28"/>
            </Grid>
            <Grid Margin="0 5" Height="75" Width="100">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock VerticalAlignment="Center" TextAlignment="Center" TextWrapping="Wrap" Text="LoremIpsum Lorem" TextDecorations="Underline" HorizontalAlignment="Center" FontSize="14" FontFamily="Georgia"/>
<TextBlock Grid.Row="1" VerticalAlignment="Center" Text="0" HorizontalAlignment="Center" FontSize="28"/>
            </Grid>
            <Grid Margin="0 5" Height="75" Width="100">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock VerticalAlignment="Center" TextAlignment="Center" TextWrapping="Wrap" Text="LoremIpsum" TextDecorations="Underline" HorizontalAlignment="Center" FontSize="14" FontFamily="Georgia"/>
<TextBlock Grid.Row="1" VerticalAlignment="Center" Text="0" HorizontalAlignment="Center" FontSize="28"/>
            </Grid>
            <Grid Margin="0 5" Height="75" Width="100">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock VerticalAlignment="Center" TextAlignment="Center" TextWrapping="Wrap" Text="LoremIpsum Lorem" TextDecorations="Underline" HorizontalAlignment="Center" FontSize="14" FontFamily="Georgia"/>
<TextBlock Grid.Row="1" VerticalAlignment="Center" Text="0" HorizontalAlignment="Center" FontSize="28"/>
            </Grid>
            <Grid Margin="0 5" Height="75" Width="100">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock VerticalAlignment="Center" TextAlignment="Center" TextWrapping="Wrap" Text="LoremIpsum" TextDecorations="Underline" HorizontalAlignment="Center" FontSize="14" FontFamily="Georgia"/>
<TextBlock Grid.Row="1" VerticalAlignment="Center" Text="0" HorizontalAlignment="Center" FontSize="28"/>
            </Grid>
            <Grid Margin="0 5" Height="75" Width="100" >
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock VerticalAlignment="Center" TextAlignment="Center" TextWrapping="Wrap" Text="LoremIpsum Lorem" TextDecorations="Underline" HorizontalAlignment="Center" FontSize="14" FontFamily="Georgia"/>
<TextBlock Grid.Row="1" VerticalAlignment="Center" Text="0" HorizontalAlignment="Center" FontSize="28"/>
            </Grid>
        </WrapPanel>
   
</Window>

@glasswizzard :
In your screenshots in post #7, you had some items which have two lines of text. Is the two lines of text intentional, or are they the result of a long line of text that gets line wrapped to two lines because you've setup a specific width for each item?

Both, I have a width and height set for each one which gives me the a limit for the length of each line to prevent them from becoming too long.

Are widths of all the items the same?

Yes, width and height are the same, you can see it in the code above.

If they are all the same, is that something you hardcoded, or is it computed somehow?

I hardcoded it, I figured out the right size to get everything neat and set them all to it.

For the two line line wrapped items, did you decide on whether you wanted the text flush to the top, flush to the bottom just above the number, or centered between the top and the number?

I managed to get them to look like the below image, which is perfect.

Annotation 2020-01-08 122702.jpg
 
Last edited:

Latest posts

Back
Top Bottom