Search code examples
c#wpfwindowswrappanel

WrapPanel hides half of the last uiElement of each line


Each UserControl I have in a stackPanel has a WrapPanel, and each UserControl in this WrapPanel is a word (so they have a different size from each other, depending on the length of the word), so that a sentence appears.

Here is an image to help you understand better:

  • In pink it is the UserControl "sentence" that contain each of them ONE wrapPanel
  • In Green it is all the UserControl "word" that have all different size according to the word length.

example so you might understand

Here is the UserControl "word":

<UserControl x:Class="Coran_seul.UC.UserControl_WordInVerse"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         xmlns:local="clr-namespace:Coran_seul.UC"
         mc:Ignorable="d" Margin="5,0,5,0">

<StackPanel>
    <TextBlock x:Name="textBlock_arabic" Text="ٱلْأَنفَالُ " FontSize="20" HorizontalAlignment="Center" FontFamily="Noto Naskh Arabic" MouseEnter="textBlock_arabic_MouseEnter" MouseLeave="textBlock_arabic_MouseLeave" Cursor="Hand" MouseDown="textBlock_arabic_MouseDown"/>
    <TextBlock x:Name="textBlock_french" Text="Les surplus (de bénéfice)" FontSize="20" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</StackPanel>

And here is the UserControl "sentence" (with the wrapPanel I have a problem with)

<UserControl x:Name="userControl" x:Class="Coran_seul.UC.UserControl_VerseInSurah"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         xmlns:local="clr-namespace:Coran_seul.UC"
         mc:Ignorable="d" Margin="0,5,0,5" 
         >
<Border x:Name="Border_Verse"  >
    <StackPanel Orientation="Horizontal" x:Name="grid">
        <Label x:Name="Label_VersetNum"  Content="2" Height="{Binding ActualHeight, ElementName=WrapPanel_Mots, Mode=OneWay}" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" VerticalAlignment="Stretch" HorizontalAlignment="Left" MouseDown="Label_VersetNum_MouseDown"/>

        <WrapPanel   x:Name="WrapPanel_Mots" Width="{Binding ActualWidth, ElementName=userControl, Mode=OneWay}" />
    </StackPanel>
</Border>

The problem :

Now that I've entered the code, here's the problem I'm having with my wrapPanel:

The last word of each line does not wrap, even if it is larger than the space left (= it is therefore hidden/cut off at the edge of the wrapPanel)

Again I have a video to better explain the problem :

https://streamable.com/lpdf38

I don't know what it's due to and I'm desperately looking since yesterday not to have this problem anymore, knowing that the stackPanel containing all the userControls has a right margin of 20 so that it's not hidden behind the scrollbar.

Please help me to find a solution so that the word as long as it is hidden even by one pixel is wrapped to the next line.

Thank you,


Solution

  • The problem is that you bind the WrapPanel's Width to that of its UserControl parent without subtracting the Width of the Label element.

    You should not need to bind any Width at all, when you use suitable Panel elements, like e.g. a Grid or a DockPanel instead of StackPanel.

    <Border x:Name="Border_Verse">
        <DockPanel>
            <Label x:Name="Label_VersetNum" DockPanel.Dock="Left" .../>
            <WrapPanel x:Name="WrapPanel_Mots">
        </DockPanel>
    </Border>
    

    <Border x:Name="Border_Verse">
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition/>
            </Grid.ColumnDefinitions>
            <Label x:Name="Label_VersetNum" Grid.Column="0" .../>
            <WrapPanel x:Name="WrapPanel_Mots" Grid.Column="1">
        </DockPanel>
    </Border>
    

    You may also consider to use an ItemsControl to display a sentence. It would use a WrapPanel as its ItemsPanel and the word UserControl in its ItemTemplate:

    <ItemsControl ItemsSource="{Binding Words}">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <WrapPanel/>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemTemplate>
            <DataTemplate>
               <uc:UserControl_VerseInSurah/>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
    

    where Words is a collection of word data item objects in the view model, i.e. the object in the DataContext of the view. The two TextBlocks in the word UserControl would have their Text property bound to an appropriate property on the word data item class.

    You may not even need the word UserControl at all, since you can simply move the elements from its XAML into the DataTemplate that is used as ItemTemplate.

    See Data Templating Overview for details.