WPF中的ListView不会填充所有可用空间

ListView in WPF not filling all available space
2020-11-25
  •  译文(汉语)
  •  原文(英语)

如何在WPF中使ListView填充所有可用空间?我尝试了很多东西,但没有一个起作用.

最近,我尝试将ListView嵌套在DockPanel中,然后在ListView上使用绑定来获取DockPanel的ActualHeight.这很好用,但是容器中还有其他控件,需要容纳它们.

我真的不需要写OnControlLoaded()和OnControlResized()事件并在代码中调整ListView的大小.我能做什么?

这是XAML,第10行带有令人讨厌的SortableListView.

    <DockPanel>
        <StackPanel DockPanel.Dock="Top" Orientation="Horizontal" Margin="15 5 5 5">
            <Button x:Name="btnAddCost" Padding="3" ToolTip="Add Cost" Margin="0 0 5 0" Click="btnAddCost_Click"  >
                Add Cost
            </Button>
            <Button x:Name="btnDeleteCost" Padding="3" ToolTip="Delete Cost" Margin="0 0 5 0" Click="btnDeleteCost_Click" IsEnabled="{Binding ElementName=lvCosts, Path=SelectedItem, Converter={StaticResource falseWhenNullConverter}}" >
                Delete Cost
            </Button>
        </StackPanel>
        <ctrls:SortableListView DockPanel.Dock="Top" x:Name="lvCosts" Margin="1" SelectionMode="Single" VerticalAlignment="Stretch" HorizontalAlignment="Stretch"
ContextMenuOpening="lvCosts_ContextMenuOpening"
DefaultActionSelected="lvCosts_DefaultActionSelected" MouseDoubleClick="lvCosts_MouseDoubleClick"
ItemsSource="{Binding Booking.AdditionalCosts}">
            <ListView.View>
                <GridView>
                    <GridViewColumn Header="Category" Width="100" DisplayMemberBinding="{Binding Path=Category.Name}" ctrls:SortableListView.SortPropertyName="Category">
                    </GridViewColumn>
                    <GridViewColumn Header="Supplier" Width="110" DisplayMemberBinding="{Binding Path=Supplier}" ctrls:SortableListView.SortPropertyName="Supplier">
                    </GridViewColumn>
                    <GridViewColumn Header="Buy Currency" Width="100" DisplayMemberBinding="{Binding Path=BuyCurrency.Name}" ctrls:SortableListView.SortPropertyName="BuyCurrency">
                    </GridViewColumn>
                    <GridViewColumn Header="Buy Price" Width="110" DisplayMemberBinding="{Binding Path=BuyPrice}" ctrls:SortableListView.SortPropertyName="BuyPrice">
                    </GridViewColumn>
                    <GridViewColumn Header="Sell Currency" Width="100" DisplayMemberBinding="{Binding Path=SellCurrency.Name}" ctrls:SortableListView.SortPropertyName="SellCurrency">
                    </GridViewColumn>
                    <GridViewColumn Header="Sell Price" Width="110" DisplayMemberBinding="{Binding Path=SellPrice}" ctrls:SortableListView.SortPropertyName="SellPrice">
                    </GridViewColumn>
                    <GridViewColumn Header="Margin" Width="180" DisplayMemberBinding="{Binding Path=Margin}" ctrls:SortableListView.SortPropertyName="Margin">
                    </GridViewColumn>
                </GridView>
            </ListView.View>
            <ListView.ContextMenu>
                <ContextMenu x:Name="mnuCostOptions" >
                    <MenuItem x:Name="mniAddCost" Header="_Add Cost" Click="mniAddCost_Click" ></MenuItem>
                    <MenuItem x:Name="mniEditCost" Header="View/_Edit Cost" Click="mniEditCost_Click" IsEnabled="False"></MenuItem>
                    <MenuItem x:Name="mniDeleteCost" Header="_Delete Cost" Click="mniDeleteCost_Click" IsEnabled="False"></MenuItem>
                </ContextMenu>
            </ListView.ContextMenu>
        </ctrls:SortableListView>
        <StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal" Margin="0,0,0,5">
            <TextBlock Grid.Row="3" Grid.Column="0">Total Buy Price:</TextBlock>
            <rdf:NumericTextBox Grid.Row="3" Grid.Column="1" IsEnabled="False" MinWidth="50" Margin="0,0,10,0">
                <rdf:NumericTextBox.Text>
                    <Binding Path="Booking.AdditionalCostsBuyPriceConvertedTotal" UpdateSourceTrigger="PropertyChanged"
Converter="{StaticResource currencyStringConverter}" ConverterParameter="#0.00" Mode="OneWay">
                    </Binding>
                </rdf:NumericTextBox.Text>
            </rdf:NumericTextBox>
            <TextBlock Grid.Row="3" Grid.Column="0">Total Sell Price:</TextBlock>
            <rdf:NumericTextBox Grid.Row="3" Grid.Column="1" IsEnabled="False" MinWidth="50" Margin="0,0,10,0">
                <rdf:NumericTextBox.Text>
                    <Binding Path="Booking.AdditionalCostsSellPriceConvertedTotal" UpdateSourceTrigger="PropertyChanged"
Converter="{StaticResource currencyStringConverter}" ConverterParameter="#0.00" Mode="OneWay">
                    </Binding>
                </rdf:NumericTextBox.Text>
            </rdf:NumericTextBox>
            <TextBlock Grid.Row="3" Grid.Column="0">Total Margin:</TextBlock>
            <rdf:NumericTextBox Grid.Row="3" Grid.Column="1" IsEnabled="False" MinWidth="50" Margin="0,0,10,0">
                <Binding Path="Booking.AdditionalCostsMarginConvertedTotal" UpdateSourceTrigger="PropertyChanged"
Converter="{StaticResource currencyStringConverter}" ConverterParameter="#0.00" Mode="OneWay">
                </Binding>
            </rdf:NumericTextBox>
            <TextBlock Grid.Column="1" Grid.Row="3" HorizontalAlignment="Right" Text="{Binding Path=Booking.SellPriceCurrency.Name, Mode=OneWay}" Margin="0,0,0,0"/>
        </StackPanel>
    </DockPanel>

谢谢,M

速聊1:
这取决于父容器是什么.发布一些XAML,以便我们提供帮助.
速聊2:
如果将其放在网格中,HorizontalAlignment="Stretch"它将延伸到您对其内部列施加的限制
速聊3:
好的,上面添加了代码.
速聊4:
容器的高度设定好了吗?(如窗口的高度)
解决过程1

您有一个DockPanel包含:

  1. StackPanel
  2. SortableListView
  3. 另一个 StackPanel

1和2都停靠在顶部;3停靠在底部.这意味着您中间没有任何东西.在2和3之间.重新排列元素的顺序以放置SortableListView第三个元素,并删除其DockPanel.Dock属性,以便占用剩余空间.

换句话说,不是您现在拥有的:

<DockPanel>
    <StackPanel DockPanel.Dock="Top" ... >
    <ctrls:SortableListView DockPanel.Dock="Top" ... >
    <StackPanel DockPanel.Dock="Bottom" ... >
</DockPanel>

更改为此:

<DockPanel>
    <StackPanel DockPanel.Dock="Top" ... >
    <StackPanel DockPanel.Dock="Bottom" ... >
    <ctrls:SortableListView ... >
</DockPanel>
速聊1:
不.那没做.外观完全相同.
速聊2:
然后,这必须归因于包含DockPanel的元素.我在第二个StackPanel中注意到您正在使用Grid附加属性(Row和Column),但是StackPanel内没有Grid.我怀疑您使用的外部网格尚未在您的问题中发布XAML.尝试为您的窗口发布所有XAML.
速聊3:
好吧,没有网格,那些附加的属性是试图使它起作用的宿醉!
速聊4:
尝试发布问题中的所有XAML,否则我将无法解决您的问题

How do I make a ListView in WPF fill all of the available space? I have tried lots and lots of things but none of them work.

Most recently I tried nesting the ListView in a DockPanel and then using a binding on the ListView to grab the DockPanel's ActualHeight. This works well but there are other controls in the container and they need to be accommodated.

I don't really want to have to write OnControlLoaded() and OnControlResized() events and resize the ListView in code. What can I do?

Here is the XAML with the offending SortableListView on line 10.

    <DockPanel>
        <StackPanel DockPanel.Dock="Top" Orientation="Horizontal" Margin="15 5 5 5">
            <Button x:Name="btnAddCost" Padding="3" ToolTip="Add Cost" Margin="0 0 5 0" Click="btnAddCost_Click"  >
                Add Cost
            </Button>
            <Button x:Name="btnDeleteCost" Padding="3" ToolTip="Delete Cost" Margin="0 0 5 0" Click="btnDeleteCost_Click" IsEnabled="{Binding ElementName=lvCosts, Path=SelectedItem, Converter={StaticResource falseWhenNullConverter}}" >
                Delete Cost
            </Button>
        </StackPanel>
        <ctrls:SortableListView DockPanel.Dock="Top" x:Name="lvCosts" Margin="1" SelectionMode="Single" VerticalAlignment="Stretch" HorizontalAlignment="Stretch"
ContextMenuOpening="lvCosts_ContextMenuOpening"
DefaultActionSelected="lvCosts_DefaultActionSelected" MouseDoubleClick="lvCosts_MouseDoubleClick"
ItemsSource="{Binding Booking.AdditionalCosts}">
            <ListView.View>
                <GridView>
                    <GridViewColumn Header="Category" Width="100" DisplayMemberBinding="{Binding Path=Category.Name}" ctrls:SortableListView.SortPropertyName="Category">
                    </GridViewColumn>
                    <GridViewColumn Header="Supplier" Width="110" DisplayMemberBinding="{Binding Path=Supplier}" ctrls:SortableListView.SortPropertyName="Supplier">
                    </GridViewColumn>
                    <GridViewColumn Header="Buy Currency" Width="100" DisplayMemberBinding="{Binding Path=BuyCurrency.Name}" ctrls:SortableListView.SortPropertyName="BuyCurrency">
                    </GridViewColumn>
                    <GridViewColumn Header="Buy Price" Width="110" DisplayMemberBinding="{Binding Path=BuyPrice}" ctrls:SortableListView.SortPropertyName="BuyPrice">
                    </GridViewColumn>
                    <GridViewColumn Header="Sell Currency" Width="100" DisplayMemberBinding="{Binding Path=SellCurrency.Name}" ctrls:SortableListView.SortPropertyName="SellCurrency">
                    </GridViewColumn>
                    <GridViewColumn Header="Sell Price" Width="110" DisplayMemberBinding="{Binding Path=SellPrice}" ctrls:SortableListView.SortPropertyName="SellPrice">
                    </GridViewColumn>
                    <GridViewColumn Header="Margin" Width="180" DisplayMemberBinding="{Binding Path=Margin}" ctrls:SortableListView.SortPropertyName="Margin">
                    </GridViewColumn>
                </GridView>
            </ListView.View>
            <ListView.ContextMenu>
                <ContextMenu x:Name="mnuCostOptions" >
                    <MenuItem x:Name="mniAddCost" Header="_Add Cost" Click="mniAddCost_Click" ></MenuItem>
                    <MenuItem x:Name="mniEditCost" Header="View/_Edit Cost" Click="mniEditCost_Click" IsEnabled="False"></MenuItem>
                    <MenuItem x:Name="mniDeleteCost" Header="_Delete Cost" Click="mniDeleteCost_Click" IsEnabled="False"></MenuItem>
                </ContextMenu>
            </ListView.ContextMenu>
        </ctrls:SortableListView>
        <StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal" Margin="0,0,0,5">
            <TextBlock Grid.Row="3" Grid.Column="0">Total Buy Price:</TextBlock>
            <rdf:NumericTextBox Grid.Row="3" Grid.Column="1" IsEnabled="False" MinWidth="50" Margin="0,0,10,0">
                <rdf:NumericTextBox.Text>
                    <Binding Path="Booking.AdditionalCostsBuyPriceConvertedTotal" UpdateSourceTrigger="PropertyChanged"
Converter="{StaticResource currencyStringConverter}" ConverterParameter="#0.00" Mode="OneWay">
                    </Binding>
                </rdf:NumericTextBox.Text>
            </rdf:NumericTextBox>
            <TextBlock Grid.Row="3" Grid.Column="0">Total Sell Price:</TextBlock>
            <rdf:NumericTextBox Grid.Row="3" Grid.Column="1" IsEnabled="False" MinWidth="50" Margin="0,0,10,0">
                <rdf:NumericTextBox.Text>
                    <Binding Path="Booking.AdditionalCostsSellPriceConvertedTotal" UpdateSourceTrigger="PropertyChanged"
Converter="{StaticResource currencyStringConverter}" ConverterParameter="#0.00" Mode="OneWay">
                    </Binding>
                </rdf:NumericTextBox.Text>
            </rdf:NumericTextBox>
            <TextBlock Grid.Row="3" Grid.Column="0">Total Margin:</TextBlock>
            <rdf:NumericTextBox Grid.Row="3" Grid.Column="1" IsEnabled="False" MinWidth="50" Margin="0,0,10,0">
                <Binding Path="Booking.AdditionalCostsMarginConvertedTotal" UpdateSourceTrigger="PropertyChanged"
Converter="{StaticResource currencyStringConverter}" ConverterParameter="#0.00" Mode="OneWay">
                </Binding>
            </rdf:NumericTextBox>
            <TextBlock Grid.Column="1" Grid.Row="3" HorizontalAlignment="Right" Text="{Binding Path=Booking.SellPriceCurrency.Name, Mode=OneWay}" Margin="0,0,0,0"/>
        </StackPanel>
    </DockPanel>

Thanks, M

Talk1:
It depends on what the parent container is. Post some XAML so we can help.
Talk2:
if you put it in a grid with HorizontalAlignment="Stretch" it will stretch to the limits you imposed on the column it's inside
Talk3:
Ok, code added above.
Talk4:
Is the height of the container set? (like the height of the window)
Solutions1

You have a DockPanel containing:

  1. StackPanel
  2. a SortableListView and
  3. another StackPanel

1 & 2 are both docked to the Top; 3 is docked to the Bottom. That means you have nothing in the middle, ie. between 2 & 3. Rearrange the order of the elements to place the SortableListView third, and remove its DockPanel.Dock property so it takes up the remaining space.

In other words, instead of what you have now:

<DockPanel>
    <StackPanel DockPanel.Dock="Top" ... >
    <ctrls:SortableListView DockPanel.Dock="Top" ... >
    <StackPanel DockPanel.Dock="Bottom" ... >
</DockPanel>

change it to this:

<DockPanel>
    <StackPanel DockPanel.Dock="Top" ... >
    <StackPanel DockPanel.Dock="Bottom" ... >
    <ctrls:SortableListView ... >
</DockPanel>
Talk1:
Nope. That didn't do it. The appearance is exactly the same.
Talk2:
Then it must be due to the element containing the DockPanel. I notice in your second StackPanel that you are using Grid attached properties (Row and Column) yet there is no Grid inside the StackPanel. I suspect you are using an outer Grid that you haven't posted the XAML for in your question. Try posting all of the XAML for your window.
Talk3:
Well there is no grid, those attached properties are hangovers of trying to get this to work!
Talk4:
Try posting all of your XAML in the question, otherwise I'm not going to be able to solve your problem
转载于:https://stackoverflow.com/questions/28028718/listview-in-wpf-not-filling-all-available-space

本人是.net程序员,因为英语不行,使用工具翻译,希望对有需要的人有所帮助
如果本文质量不好,还请谅解,毕竟这些操作还是比较费时的,英语较好的可以看原文

留言回复
我们只提供高质量资源,素材,源码,坚持 下了就能用 原则,让客户花了钱觉得值
上班时间 : 周一至周五9:00-17:30 期待您的加入