C# 布局问题试图使ListView显示固定数量的项目

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 当要开始的

在UWP项目中,我有一个
列表视图
,它绑定到
个人
对象的
可观察集合
。我使用
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>