2
votes

I have a Listbox and each listbox item contain a DockPanel with two elements TextBlock and a Label. Following is the xaml Code -

        <ListBox HorizontalContentAlignment="Stretch" ScrollViewer.HorizontalScrollBarVisibility="Disabled">
           <ListBoxItem>
            <DockPanel>
                <TextBlock Text="Ted its so wonderfull I am gere asdf asdf asdf adsf asdf asdf asdfasf asfd asf asdf asdf asdf asdf asdasfd asf " TextWrapping="Wrap"></TextBlock>
                <Label Content="Click Me" HorizontalAlignment="Right"></Label>
            </DockPanel>                
        </ListBoxItem>

        <ListBoxItem>
            <DockPanel>
                <TextBlock Text="Ted its so wonderfull Ted its so wonderfull I am gere asdf asdf asdf adsf asdf asdf asdfasf asfd asf asdf asdf asdf asdf asdasfd asf" TextWrapping="Wrap"></TextBlock>
                <Label Content="Click Me" HorizontalAlignment="Right"></Label>
            </DockPanel>
        </ListBoxItem>
    </ListBox>

So I was expecting a window where each row will have two elements first coloumn is the text block and the next one is a label. I added the HorizonatalContentAlignment=stretch and HorizontalAlignment=Right for labels for when user resize the window the label should go to the right end.

But the issue I am facing with the above code is when I resize the window and when the text block start to wrap, Textblock is hiding/overlapping the Label element. In some case the label is completely hidden, when a word in the text block perfectly align with the right end of the window, or is partially hidden ?

Why the second element is getting overlapped or hidden ? I want to show the click me label always, How to achieve this ?

2

2 Answers

3
votes

Just to point out that in other scenarios like unknown number of Elements to be added to a ListBoxItem content for example, using a DockPanel is not that bad.

Example :

  • First item in the ListBox, I want a Text and a Label.
  • Secund item, I want a Text, a Label and a Button.
  • and so on...

With a Grid, it won't work unless you add a lot of things (either using ContentTemplate and Bindings or even Code behind) and that's where a DockPanel is usefull.

What's wrong in your approach is that you've put the TextBlock before the Label. In DockPanel, order matters and first item takes precedence over the secund, the secund over the third... and if a previous item has taken all the remaining space (which your TextBlock did with its very long Text value) then any other following item will not be drawn as expected.

And don't forget to specify the Docking mode.

So, just for clarification, there's nothing wrong using a DockPanel here, but items order matters.

<ListBox HorizontalContentAlignment="Stretch" 
    ScrollViewer.HorizontalScrollBarVisibility="Disabled">
    <ListBoxItem>
        <DockPanel>
            <!-- Declare your Label first and dock it to the right -->
            <Label 
                DockPanel.Dock="Right" />
            <TextBlock 
                Text="Ted its so wonderfull I am gere asdf asdf asdf adsf asdf asdf asdfasf asfd asf asdf asdf asdf asdf asdasfd asf " TextWrapping="Wrap" />
        </DockPanel>                
    </ListBoxItem>

    <!-- ... -->

</ListBox>

Some UIElements like Label doesn't (really) require HorizontalAlignment when they are Left/Right docked inside a DockPanel. In that case, only the VerticalAlignment matters.

Rule is :

  • Remember that a DockPanel allocates a rectangular area for each item.
  • Items get that allocated area in order.
  • DockPanel default the docking to the left.
  • DockPanel better works with a list of items occupying a small area that are declared first and docked accordingly, then a last item of variable size that will fill the remaining space if available.
  • DockPanel will always try to show at least a small piece of every item when the available area is not sufficiently wide (so carefully add constrains when you want an item to remain fully visible, like putting the DockPanel inside a Grid Column or Row ;) )

In the end, this is an answer that explains why the Label is overlapped by the TextBlock – for other readers wanting to master a DockPanel.

But yeah, when I already know how many items I'm going to have in a container, I'll use a Grid, 99% of the time, because I can bind Row and Columns size directly, while with a DockPanel, StackPanel, etc, I would have to reference each contained item one by one.

I do agree with the accepted answer :)

2
votes

You could use a Grid. The first column uses all available space, where the second column reserves space for the 'click' label.

        <ListBoxItem>
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*"></ColumnDefinition>
                    <ColumnDefinition Width="Auto"></ColumnDefinition>
                </Grid.ColumnDefinitions>
                <TextBlock Text="Ted its so wonderfull I am gere asdf asdf asdf adsf asdf asdf asdfasf asfd asf asdf asdf asdf asdf asdasfd asf " TextWrapping="Wrap"></TextBlock>
                <Label Grid.Column="1" Content="Click Me" HorizontalAlignment="Right"></Label>
            </Grid>
        </ListBoxItem>

The image below shows the grid compared to the dock approach.

enter image description here