在UWP项目中,我有ListView
绑定到ObservableCollection<T>
个Person
个对象。我使用DataTemplate
在Person
中显示ListView
对象。集合(人员)最多只能包含由_maxPeopleCount
设置的一定数量的人。
我希望发生的是ListView
:
Person
定义的所有_maxPeopleCount
个对象。Person
个对象,而不是部分显示。也就是说,显示每个项目,以便ListViewItem.Height =(来自ItemsPanel的可用高度)/ _maxPeopleCount
。_maxPeopleCount
个项目时,仍会显示添加的项目,其中包含(3)中定义的高度。目前我无法让我的项目做到这一点。
任何人都可以帮忙解决这个问题或建议其他方法吗?
以下是显示问题的示例代码。只需按下按钮7次以上,因为这是代码中的_maxPeopleCount
。你会看到7人没有出现。为可怕的UI道歉。它用最小的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}"));
}
XAML:
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<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 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"/>
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<ItemsStackPanel HorizontalAlignment="Stretch"/>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemTemplate>
<DataTemplate>
<Grid x:Name="grdPerson">
<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>
PERSON CLASS:
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;
}
答案 0 :(得分:1)
根本不滚动。
为此,您已经完成了ScrollViewer.VerticalScrollMode="Disabled" ScrollViewer.VerticalScrollBarVisibility="Hidden"
。
显示_maxPeopleCount定义的所有Person对象。
实际上,您已将_maxPeopleCount
个人记录绑定到ListView
,但受窗口大小的限制,您无法全部看到它们。那里存在不可见的记录。如果通过手动拖动拉伸应用程序窗口大小以使高度更大,您将看到剩余的记录。如果您希望始终显示所有记录,您可能需要自己计算ListViewItem
高度。
完全显示每个Person对象,而不是部分显示。也就是说,显示每个项目以便ListViewItem.Height =(来自ItemsPanel的可用高度)/ _maxPeopleCount。
在您的方案中,ListViewItem
的高度会自动计算,因为您没有为其设置修复高度。正如您在此处显示的公式,我们可以在代码后面动态绑定ListViewItem
的{{3}}类的高度。请注意窗口大小更改会影响ListView
的实际大小,因此我们还需要在应用窗口大小更改时调整ListViewItem
的大小。当ListViewItem
的高度设置为小于44
时,它将不会生效,因为ViewTreeHelper
的默认MinHeight
为44
,需要重置。有关实施此要求的更多设置,请参阅下面的演示。
当小于_maxPeopleCount的项目开始时,仍会显示添加的项目,其中包含(3)中定义的高度。
计算完成后,ListViewItem
的所有高度都相同。
将每个Person的FirstName和LastName显示为尽可能大。
为此,您<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
要展开水平内容,请同时按<Setter Property="VerticalContentAlignment" Value="Stretch"/>
拉伸垂直内容。 padding
ListviewItem
需要设置为0
。
更新了以下代码,现在可以满足您的所有要求。
XAML
<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;
}
}
}
}
}
答案 1 :(得分:1)
您可以随时编写自己的Panel,这很容易。这是我写的UniformStackPanel,它像StackPanel一样工作,但它会拉伸每个项目以填充可用空间(无论它有多少项目)。
Ctrl + PageDown
将它与ItemsControl一起使用,如下所示:
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;
}
}
答案 2 :(得分:0)
好的,我想我已经破解了!我将ItemsPanelTemplate
更改为here的UniformGrid
面板。它是WPF具有的UWP版本,因此您可以设置行数和列数。对于我上面的例子,Rows = 7,Columns = 1。
之后我改变的是在Setter
中添加以下额外的ItemContainerStyle
:
<Setter Property="VerticalContentAlignment" Value="Stretch"/>
修复了ListViewItems
内容未被最大化的问题。
希望这有助于他人,并为那些在帮助下回复的人欢呼。