0
votes

I'm going nuts trying to figure this out. I've got a DockPanel with some stuff docked to Top, and an ItemsControl as its center content (which presents itself as a WrapPanel containing more DockPanels).

I want the center ItemsControl to expand the width of the parent DockPanel as necessary. I don't want the stuff docked to the top of the DockPanel to cause the DockPanel to expand, but I would like it to use whatever space has been requested by the width of the ItemsControl.

Here's some greatly simplified XAML that still captures the behavior:

<Window x:Class="SizingTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" SizeToContent="Width" Height="150">
    <Grid>
        <DockPanel>
            <TextBlock DockPanel.Dock="Top">Here's some really long text that should not force the window to expand. Just clip if it's wider than the buttons.</TextBlock>
            <WrapPanel Orientation="Vertical">
                <Button>Button 1</Button>
                <Button>Button 2</Button>
                <Button>Button 3</Button>
                <Button>Button 4</Button>
                <Button>Button 5</Button>
                <Button>Button 6</Button>
                <Button>Button 7</Button>
                <Button>Button 8</Button>
                <Button>Button 9</Button>
                <Button>Button 10</Button>
            </WrapPanel>
        </DockPanel>
    </Grid>
</Window>

In other words, the WrapPanel/DockPanel/Grid/Window should adjust their width to accommodate the WrapPanel's columns of Buttons, but I want the TextBlock to simply be clipped after exhausting all the available space that the WrapPanel requested. Resizing the window height (which causes the WrapPanel to adjust itself and add/remove columns) should cause the TextBlock to change width - and clip - to match the WrapPanel. How do I make that work?

2

2 Answers

2
votes

You just need to make a couple of changes. First, you need the WrapPanel to not stretch across the full Width. Then you can data bind the TextBlock.Width property to the WrapPanel.ActualWidth property. Finally, you'll also need to set the HorizontalAlignment property to Left on the TextBlock as well. This should do the trick:

<Grid>
    <DockPanel>
        <TextBlock DockPanel.Dock="Top" HorizontalAlignment="Left" 
            Width="{Binding ActualWidth, ElementName=Panel}" Text="Here's some really 
            long text that should not force the window to expand..." />
        <WrapPanel Name="Panel" Orientation="Vertical" HorizontalAlignment="Left">
            <Button>Button 1</Button>
            <Button>Button 2</Button>
            <Button>Button 3</Button>
            <Button>Button 4</Button>
            <Button>Button 5</Button>
            <Button>Button 6</Button>
            <Button>Button 7</Button>
            <Button>Button 8</Button>
            <Button>Button 9</Button>
            <Button>Button 10</Button>
        </WrapPanel>
    </DockPanel>
</Grid>

A final note is that it would look better if you used the TextTrimming property to add an ellipsis (...) at the end of the text just before it is cut off. You could do that like this:

<TextBlock DockPanel.Dock="Top" HorizontalAlignment="Left" Width="{Binding ActualWidth,
    ElementName=Panel}" Text="Here's some really long text that should not force the 
    window to expand..." TextTrimming="CharacterEllipsis" />

enter image description here

0
votes

You could take a look at this and maybe you will find the solution to your issue in there:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="150"
        xmlns:local="clr-namespace:WpfApplication1">
    <Grid>
        <DockPanel LastChildFill="False">
            <TextBlock DockPanel.Dock="Top">
                Here's some really long text that should not force the window to expand. Just clip if it's wider than the buttons.
            </TextBlock>
            <WrapPanel x:Name="wrapPanel" DockPanel.Dock="Left" Orientation="Vertical">
                <Button>Button 1</Button>
                <Button>Button 2</Button>
                <Button>Button 3</Button>
                <Button>Button 4</Button>
                <Button>Button 5</Button>
                <Button>Button 6</Button>
                <Button>Button 7</Button>
                <Button>Button 8</Button>
                <Button>Button 9</Button>
                <Button>Button 10</Button>
            </WrapPanel>
        </DockPanel>
    </Grid>
</Window>

Tell the DockPanel not to fill out its available space with the last child in order to prevent WrapPanel from stretching. In the end tell the window to take the calculated width of the WrapPanel like this:

public MainWindow()
{
    InitializeComponent();
    this.wrapPanel.Loaded += wrapPanel_Loaded;
}

void wrapPanel_Loaded(object sender, RoutedEventArgs e)
{
    this.Width = this.wrapPanel.ActualWidth + 20;
}

That would be it. Text will be clipped off though when you resize the window the text will calculate new clipping.