开发者

WPF Layout - Geting a column to fill available space

开发者 https://www.devze.com 2022-12-13 01:06 出处:网络
I have a ListBox that has a grid in its template to allow 4 columns.One column is the actual text of the ListBox.I want that column to fill the available horizontal space.

I have a ListBox that has a grid in its template to allow 4 columns. One column is the actual text of the ListBox. I want that column to fill the available horizontal space.

The column definitions are:

<ControlTemplate TargetType="ListBoxItem">
    <Grid ScrollViewer.CanContentScroll="True" Margin="2">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="20" />
            <ColumnDefinition Width="50" />
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="30" />
        </Grid.ColumnDefinitions>
        <CheckBox VerticalAlignment="Center" Grid.Column="0" IsChecked="{Binding IsSelected,
                  RelativeSource={RelativeSource TemplatedParent},
                  Mode=TwoWay}" />
        <TextBlock VerticalAlignment="Center" Grid.Column="1" Margin="5,0,5,0" Text="{Binding Id}" />
        <TextBlock VerticalAlignment="Center" Grid.Column="2" Margin="5,0,5,0" Text="{Binding Title}" />
        <Button HorizontalAlignment="Right" Grid.Column="3" Tag="{Binding Id}" Margin="5,0,5,0"&g开发者_C百科t;-&gt;</Button>
    </Grid>
</ControlTemplate>

I have tried several permutations of this and nothing will get it to fix in the window except for an explicit size setting. Then when I resize the window it does not resize with it.

The ListBox is wrapped in a ScrollViewer to allow vertical scrolling (I am guessing that is what is messing me up.)

Any ideas on how to get the third column to fill just the available space and no more?


Do you need the control behaviours of ListBox, or are you using it for layout only.

If you are using it just for layout, you could swap the ListBox for a ItemsControl inside of a ScrollViewer.

This code (butchered to work in designer) show this:

<ScrollViewer>
    <ItemsControl>
        <!--<ListBox>-->
        <Grid Margin="2">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="20" />
                <ColumnDefinition Width="50" />
                <ColumnDefinition Width="*" />
                <ColumnDefinition Width="30" />
            </Grid.ColumnDefinitions>

            <CheckBox VerticalAlignment="Center" Grid.Column="0" IsChecked="True" />
            <TextBlock VerticalAlignment="Center" Grid.Column="1" Margin="5,0,5,0" Text="Id" />
            <TextBlock VerticalAlignment="Center" Grid.Column="2" Margin="5,0,5,0" Text="Title" />
            <Button HorizontalAlignment="Right" Grid.Column="3" Margin="5,0,5,0">-&gt;</Button>
        </Grid>
        <!--</ListBox>-->
    </ItemsControl>
</ScrollViewer>

The ListBox has some property of killing width on it's children, just like a TreeView does. So if you can avoid using it, for just layout reasons, this may be your fastest options.

Otherwise you'll need to databind the width of you Grid to the width of the dummy object outside the ListView, but the messy party is dealing with the width change as the scrollbar appears/disappears.


Why do you need to wrap the ListBox in a ScrollViewer? The ListBox automatically displays the ScrollViewer when its contents don't fit in the available space. You can remove it from the XAML and it should still work okay. At least, it did for me. :)

I tried your ControlTemplate out and it seemed to work really well. The problem is that while the 3rd column resizes to the width of the ListBox, if the text in the 3rd column is very long, the 4th column won't appear until all of the text is visible.

I also tried another layout method, which I'm not sure about performance-wise, but the idea was to use a DockPanel instead of a Grid. I added the third column last in the XAML to make it fill the remaining space, and docked it to the left (I docked the 4th column to the right). It still would want to display the entire string in the 3rd column. I don't know why this is happening, and why the text won't wrap or use an ellipsis when the available space isn't enough for the text to display.

<Window.Resources>
    <Style TargetType="ListBoxItem">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="ListBoxItem">
                    <DockPanel Width="Auto">
                        <CheckBox Width="20" VerticalAlignment="Center" DockPanel.Dock="Left" IsChecked="{Binding IsSelected,
                                        RelativeSource={RelativeSource TemplatedParent},
                                        Mode=TwoWay}" />
                        <TextBlock Width="50" VerticalAlignment="Center" DockPanel.Dock="Left" Margin="5,0,5,0" Text="hi" />
                        <Button Width="30" HorizontalAlignment="Right" DockPanel.Dock="Right" Margin="5,0,5,0">-&gt;</Button>
                        <TextBlock VerticalAlignment="Center" DockPanel.Dock="Left" Margin="5,0,5,0" Text="afdjfksdhahjklfadshjlasffasdlhjsafdlhjasdfasfhdjlaslfhdjsfdhjlsfdlhjsfdhjsfdddsd" TextTrimming="CharacterEllipsis" TextWrapping="WrapWithOverflow" />
                    </DockPanel>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</Window.Resources>   


Yes I would suggest the scroll viewer is messing you up, you could bind the Grid's width to the parent objects actual width, so there is a defined size in which the * has to actually fill.


I finally figure this out.

The containing list box needed to set the horizontal scroll bar to disabled like this:

<ListBox ScrollViewer.HorizontalScrollBarVisibility="Disabled" 

Once I did that the grid sized perfectly.

One of these days I will figure out how all this "declarative stuff" works.

0

精彩评论

暂无评论...
验证码 换一张
取 消