C# 布局问题试图使ListView显示固定数量的项目
在UWP项目中,我有一个C# 布局问题试图使ListView显示固定数量的项目,c#,xaml,listview,layout,uwp,C#,Xaml,Listview,Layout,Uwp,在UWP项目中,我有一个列表视图,它绑定到个人对象的可观察集合。我使用DataTemplate在列表视图中显示Person对象。集合(人员)最多只能包含由\u maxPeopleCount设置的特定数量的人员 我希望列表视图能够: 根本不滚动 显示由\u maxPeopleCount定义的所有Person对象 完整显示每个人对象,而不是部分显示。也就是说,显示每个项目,以便ListViewItem.Height=(ItemsPanel中的可用高度)/\u maxPeopleCount 当要开始的
列表视图
,它绑定到个人
对象的可观察集合
。我使用DataTemplate
在列表视图中显示Person
对象。集合(人员)最多只能包含由\u maxPeopleCount
设置的特定数量的人员
我希望列表视图
能够:
根本不滚动
显示由\u maxPeopleCount
定义的所有Person
对象
完整显示每个人
对象,而不是部分显示。也就是说,显示每个项目,以便ListViewItem.Height=(ItemsPanel中的可用高度)/\u maxPeopleCount
当要开始的项目少于\u maxPeopleCount
时,仍显示添加的项目,其高度如(3)中所定义
将每个人的名字和姓氏显示得尽可能大
目前,我无法让我的项目做到这一点
下面是显示问题的示例代码。只需按下按钮7次以上,因为这是代码中的\u maxPeopleCount
。你会看到7个人没有被展示。为糟糕的用户界面道歉。它的目的是用最小的XAML来显示问题,但与我的实际项目类似
代码隐藏:
public sealed partial class MainPage : Page
{
ObservableCollection<Person> _people = new ObservableCollection<Person>();
int _personCount = 0;
int _maxPeopleCount = 7;
public MainPage()
{
this.InitializeComponent();
this.DataContext = _people;
}
private void btnAddPerson_Click(object sender, RoutedEventArgs e)
{
if (_people.Count == _maxPeopleCount)
{
_people.RemoveAt(_people.Count - 1);
}
_personCount += 1;
_people.Insert(0, new Person($"FirstName {_personCount}", $"LastName {_personCount}"));
}
根本不滚动
为此,您已经通过ScrollViewer.VerticalScrollMode=“Disabled”ScrollViewer.VerticalScrollBarVisibility=“Hidden”
完成了
显示由_maxPeopleCount定义的所有Person对象
实际上,您已经将\u maxPeopleCount
个人记录绑定到列表视图
,但受窗口大小的限制,您无法看到所有记录。看不见的记录确实存在。如果通过手动拖动来拉伸应用程序窗口的大小,使其高度更大,则会看到剩余的记录。如果要使所有记录始终可见,可能需要自己计算ListViewItem
高度
完全显示每个人的对象,而不是部分显示。也就是说,显示每个项目,以便ListViewItem.Height=(ItemsPanel中的可用高度)/\u maxPeopleCount
在您的场景中,ListViewItem
的高度是自动计算的,因为您没有为其设置固定高度。正如您在这里展示的公式,我们可以在代码隐藏中按类动态绑定ListViewItem
的高度。请注意,窗口大小的更改将影响列表视图的实际大小,因此当应用程序更改窗口大小时,我们还需要调整列表视图项的大小。当ListViewItem
的高度设置为小于44
时,它不会生效,因为默认的MinHeight
为44
,需要重置。有关实现此要求的更多设置,请参考下面的演示
当要开始的maxPeopleCount项目少于_时,仍会显示添加的项目,其高度如(3)中所定义
计算后,所有的ListViewItem
将具有相同的高度
将每个人的名字和姓氏显示得尽可能大
为此,您有
来拉伸水平内容,也请通过
拉伸垂直内容。需要将ListviewItem
的padding
设置为0
更新代码如下,现在可以满足您的所有上述要求
XAML
代码隐藏
public sealed partial class MainPage : Page
{
ObservableCollection<Person> _people = new ObservableCollection<Person>();
int _personCount = 0;
int _maxPeopleCount = 7;
public MainPage()
{
this.InitializeComponent();
this.DataContext = _people;
Window.Current.SizeChanged += Current_SizeChanged;
}
public void resize()
{
var listpersonheight = listperson.ActualHeight;
IEnumerable<ListViewItem> items = FindVisualChildren<ListViewItem>(listperson);
for (int i = 0; i < items.Count(); i++)
{
foreach (ListViewItem item in items)
{
item.Height = (listpersonheight - 10) / _maxPeopleCount;// BorderThickness size need to be minus.
item.Width = listperson.ActualWidth - 10; //Width also need resize.
}
}
}
private void Current_SizeChanged(object sender, Windows.UI.Core.WindowSizeChangedEventArgs e)
{
resize();
}
private void grdPerson_Loaded(object sender, RoutedEventArgs e)
{
resize();
}
private void btnAddPerson_Click(object sender, RoutedEventArgs e)
{
if (_people.Count == _maxPeopleCount)
{
_people.RemoveAt(_people.Count - 1);
}
_personCount += 1;
_people.Insert(0, new Person($"FirstName {_personCount}", $"LastName {_personCount}"));
}
private static IEnumerable<T> FindVisualChildren<T>(DependencyObject depObj) where T : DependencyObject
{
if (depObj != null)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
if (child != null && child is T)
{
yield return (T)child;
}
foreach (T childOfChild in FindVisualChildren<T>(child))
{
yield return childOfChild;
}
}
}
}
}
公共密封部分类主页面:第页
{
ObservableCollection_people=新的ObservableCollection();
int_personCount=0;
int_maxPeopleCount=7;
公共主页()
{
this.InitializeComponent();
this.DataContext=\u人;
Window.Current.SizeChanged+=当前_SizeChanged;
}
public void resize()
{
var listpersonheight=listperson.ActualHeight;
IEnumerable items=FindVisualChildren(listperson);
对于(int i=0;i public class Person : INotifyPropertyChanged
{
public Person(string firstName, string lastName)
{
FirstName = firstName;
LastName = lastName;
}
private string _firstName = string.Empty;
public string FirstName
{
get { return _firstName; }
set
{
_firstName = value;
OnPropertyChanged();
}
}
private string _lastName = string.Empty;
public string LastName
{
get { return _lastName; }
set
{
_lastName = value;
OnPropertyChanged();
}
}
protected void OnPropertyChanged([CallerMemberName] string caller = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(caller));
}
public event PropertyChangedEventHandler PropertyChanged;
}
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" x:Name="gridroot">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Button Grid.Row="0" Grid.Column="0" x:Name="btnAddPerson" Click="btnAddPerson_Click" Content="Add Person" VerticalAlignment="Center" HorizontalAlignment="Center"/>
<ListView x:Name="listperson" BorderBrush="Black" BorderThickness="5" Margin="10" Grid.Row="1" Grid.Column="0" ItemsSource="{Binding}" ScrollViewer.VerticalScrollMode="Disabled" ScrollViewer.VerticalScrollBarVisibility="Hidden" ScrollViewer.HorizontalScrollBarVisibility="Hidden" ScrollViewer.HorizontalScrollMode="Disabled" VerticalAlignment="Stretch" VerticalContentAlignment="Stretch" HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="VerticalContentAlignment" Value="Stretch"/>
<Setter Property="MinHeight" Value="20"/>
<Setter Property="Padding" Value="0"/>
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<ItemsStackPanel HorizontalAlignment="Stretch"/>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemTemplate>
<DataTemplate>
<Grid x:Name="grdPerson" Loaded="grdPerson_Loaded" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Border Grid.Column="0" Background="Green" HorizontalAlignment="Stretch" >
<Viewbox>
<TextBlock Text="{Binding FirstName}" HorizontalAlignment="Stretch" />
</Viewbox>
</Border>
<Border Grid.Column="1" Background="Yellow" HorizontalAlignment="Stretch">
<Viewbox>
<TextBlock Text="{Binding LastName}" HorizontalAlignment="Stretch" />
</Viewbox>
</Border>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
public sealed partial class MainPage : Page
{
ObservableCollection<Person> _people = new ObservableCollection<Person>();
int _personCount = 0;
int _maxPeopleCount = 7;
public MainPage()
{
this.InitializeComponent();
this.DataContext = _people;
Window.Current.SizeChanged += Current_SizeChanged;
}
public void resize()
{
var listpersonheight = listperson.ActualHeight;
IEnumerable<ListViewItem> items = FindVisualChildren<ListViewItem>(listperson);
for (int i = 0; i < items.Count(); i++)
{
foreach (ListViewItem item in items)
{
item.Height = (listpersonheight - 10) / _maxPeopleCount;// BorderThickness size need to be minus.
item.Width = listperson.ActualWidth - 10; //Width also need resize.
}
}
}
private void Current_SizeChanged(object sender, Windows.UI.Core.WindowSizeChangedEventArgs e)
{
resize();
}
private void grdPerson_Loaded(object sender, RoutedEventArgs e)
{
resize();
}
private void btnAddPerson_Click(object sender, RoutedEventArgs e)
{
if (_people.Count == _maxPeopleCount)
{
_people.RemoveAt(_people.Count - 1);
}
_personCount += 1;
_people.Insert(0, new Person($"FirstName {_personCount}", $"LastName {_personCount}"));
}
private static IEnumerable<T> FindVisualChildren<T>(DependencyObject depObj) where T : DependencyObject
{
if (depObj != null)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
if (child != null && child is T)
{
yield return (T)child;
}
foreach (T childOfChild in FindVisualChildren<T>(child))
{
yield return childOfChild;
}
}
}
}
}
<Setter Property="VerticalContentAlignment" Value="Stretch"/>
public class UniformStackPanel : StackPanel
{
protected override Size MeasureOverride(Size availableSize)
{
var childSize = Orientation == Orientation.Horizontal ?
new Size(availableSize.Width / Children.Count, availableSize.Height) :
new Size(availableSize.Width, availableSize.Height / Children.Count);
double alongAxis = 0;
double crossAxis = 0;
foreach (var child in Children)
{
child.Measure(childSize);
if (Orientation == Orientation.Horizontal)
{
alongAxis += child.DesiredSize.Width;
crossAxis = Math.Max(crossAxis, child.DesiredSize.Height);
}
else
{
alongAxis += child.DesiredSize.Height;
crossAxis = Math.Max(crossAxis, child.DesiredSize.Width);
}
}
return Orientation == Orientation.Horizontal ?
new Size(alongAxis, crossAxis) :
new Size(crossAxis, alongAxis);
}
protected override Size ArrangeOverride(Size finalSize)
{
var childSize = Orientation == Orientation.Horizontal ?
new Size(finalSize.Width / Children.Count, finalSize.Height) :
new Size(finalSize.Width, finalSize.Height / Children.Count);
double alongAxis = 0;
foreach (var child in Children)
{
if (Orientation == Orientation.Horizontal)
{
child.Arrange(new Rect(alongAxis, 0, childSize.Width, childSize.Height));
alongAxis += childSize.Width;
}
else
{
child.Arrange(new Rect(0, alongAxis, childSize.Width, childSize.Height));
alongAxis += childSize.Height;
}
}
return finalSize;
}
}
<ItemsControl BorderBrush="Black" BorderThickness="5" Margin="10" Grid.Row="1" ItemsSource="{Binding}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<local:UniformStackPanel/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Border Grid.Column="0" Background="RoyalBlue" HorizontalAlignment="Stretch">
<Viewbox>
<TextBlock Text="{Binding FirstName}"/>
</Viewbox>
</Border>
<Border Grid.Column="1" Background="Crimson" HorizontalAlignment="Stretch">
<Viewbox>
<TextBlock Text="{Binding LastName}"/>
</Viewbox>
</Border>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>