Dre*_*eep 5 c# wpf xaml itemscontrol
我有一个窗口,其中包含一个ItemsControl内部可以包含可变数量控件的窗口。为了考虑到超出窗口高度的情况,我将其包装在 a 中ScrollViewer,以便当项目数量超过可用高度时会显示滚动条。
现在的问题是,有时不会显示任何内容ItemsControl,有时却会显示。因此,我将网格行的高度设置为 ,Auto以允许 网格ItemsControl行在空时消失,或在需要时增长。但是,这意味着该行将占用所需的高度,即使这超出了窗口高度,并且永远不会显示垂直滚动条。
以下是演示该问题的示例窗口的一些 XAML...
<Window x:Class="DuplicateCustomerCheck.TestScrollViewerWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Test Scroll Viewer Window"
Height="450"
Width="200">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBox Name="N"
TextChanged="TextBoxBase_OnTextChanged"
Grid.Row="0"
Margin="3" />
<Grid Margin="3"
Grid.Row="1">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock Text="Possible duplicate of..."
Margin="3" />
<ScrollViewer VerticalScrollBarVisibility="Visible"
Grid.Row="1">
<ItemsControl Name="MatchingNames"
ItemsSource="{Binding MatchingNames, Mode=TwoWay}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Content="{Binding Item}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</Grid>
<TextBlock Grid.Row="2"
Margin="3"
Text="Stuff at the bottom" />
</Grid>
</Window>
Run Code Online (Sandbox Code Playgroud)
出于演示目的,这里是按钮的事件处理程序,它允许我测试不同数量的项目(请注意,这是 noddy 代码,因此没有错误检查等)...
private void TextBoxBase_OnTextChanged(object sender, TextChangedEventArgs e) {
MatchingNames.ItemsSource = Enumerable
.Range(0, int.Parse(N.Text))
.Select(n1 => new {
Item = "Button " + n1
});
}
Run Code Online (Sandbox Code Playgroud)
如果我将第二个网格行的高度更改为,*那么它可以正常工作,但这意味着它ItemsControl永久可见,这是我不想要的。仅当其中有某些项目时才应显示它。
我尝试了这篇博客文章ScrollViewerMaxSizeBehavior中的行为(代码在这里),但它没有任何区别。
任何人都知道我如何允许它ItemsControl占据所需的垂直空间,包括零,但不长得比窗口能容纳的高度?
这种情况仅通过 XAML 来解决是很棘手的。我会通过一些计算来解决它\xe2\x80\xa6
\n\n<Grid x:Name="MyGrid">\n <Grid.RowDefinitions>\n <RowDefinition Height="Auto" />\n <RowDefinition Height="Auto" MaxHeight="{Binding Row2MaxHeight}"/>\n <RowDefinition Height="Auto" />\n </Grid.RowDefinitions>\n\n <TextBox Name="N" TextChanged="TextBoxBase_OnTextChanged" Grid.Row="0" Margin="3" />\n\n <Grid Margin="3" Grid.Row="1" x:Name="MyInnerGrid">\n <Grid.RowDefinitions>\n <RowDefinition Height="Auto"/>\n <RowDefinition Height="Auto" />\n </Grid.RowDefinitions>\n <TextBlock Text="Possible duplicate of..." Margin="3" />\n <ScrollViewer Grid.Row="1" MaxHeight="{Binding Row2MaxHeightInner}">\n <ItemsControl Name="MatchingNames" ItemsSource="{Binding MatchingNames, Mode=TwoWay}">\n <ItemsControl.ItemsPanel>\n <ItemsPanelTemplate>\n <StackPanel Orientation="Vertical" />\n </ItemsPanelTemplate>\n </ItemsControl.ItemsPanel>\n\n <ItemsControl.ItemTemplate>\n <DataTemplate>\n <Button Content="{Binding Item}" />\n </DataTemplate>\n </ItemsControl.ItemTemplate>\n </ItemsControl>\n </ScrollViewer>\n </Grid>\n\n <TextBlock Grid.Row="2"\n Margin="3"\n Text="Stuff at the bottom" />\n</Grid>\nRun Code Online (Sandbox Code Playgroud)\n\n和代码:
\n\npublic partial class MainWindow : Window, INotifyPropertyChanged {\n public MainWindow() {\n InitializeComponent();\n\n DataContext = this;\n SizeChanged += SizeWasChanged;\n }\n\n private void SizeWasChanged(object sender, SizeChangedEventArgs e) {\n OnPropertyChanged(nameof(Row2MaxHeight));\n OnPropertyChanged(nameof(Row2MaxHeightInner));\n }\n\n public double Row2MaxHeight => ActualHeight - MyGrid.RowDefinitions[0].ActualHeight - MyGrid.RowDefinitions[2].ActualHeight - 50; //50 or something is around the Size of the title bar of the window\n public double Row2MaxHeightInner => Row2MaxHeight - MyInnerGrid.RowDefinitions[0].ActualHeight - 6; //6 should match the margin of the scrollviewer\n\n private void TextBoxBase_OnTextChanged(object sender, TextChangedEventArgs e) {\n MatchingNames.ItemsSource = Enumerable\n .Range(0, int.Parse(N.Text))\n .Select(n1 => new {\n Item = "Button " + n1\n });\n OnPropertyChanged(nameof(Row2MaxHeight));\n OnPropertyChanged(nameof(Row2MaxHeightInner));\n }\n\n public event PropertyChangedEventHandler PropertyChanged;\n\n [NotifyPropertyChangedInvocator]\n protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) {\n PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n