[英]Autosize column in ListView (UWP)
I would like to arrange my items in a ListView with a Text and an image like in this example: 我想将我的项目排列在具有文本和图像的ListView中,如以下示例所示:
So, how can I make an Auto column... or simulate it? 那么,如何制作自动列...或对其进行仿真?
Obviously, the difficult part of this layout is that different elements have their widths depending on other element's widths. 显然,此布局的困难之处在于不同元素的宽度取决于其他元素的宽度。
EDIT: Using @WPInfo's answer, I've tried with this: 编辑:使用@WPInfo的答案,我已经尝试过:
XAML XAML
<Page.DataContext>
<local:MainViewModel></local:MainViewModel>
</Page.DataContext>
<ListView ItemsSource="{Binding Items}">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding}" />
<Border Background="CornflowerBlue" Grid.Column="1" />
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
CODE: 码:
public class MainViewModel
{
public IList<string> Items { get; }
public MainViewModel()
{
Items = new List<string>()
{
"ABC",
"ABCDEF",
"ABCDEFGHI",
};
}
}
The expected result was: 预期结果是:
However, the actual result is: 但是,实际结果是:
The goal is that the first column to be as wide as the widest element inside it. 目的是使第一列与它内部的最宽元素一样宽。
In WPF, this is solved easily with the use of Grid.SharedSizeGroup
. 在WPF中,可以使用
Grid.SharedSizeGroup
轻松解决此问题。 In UWP there is not such a thing. 在UWP中没有这样的事情。
The problem is that ListView children don't know anything about each other. 问题在于ListView子级彼此之间一无所知。 There's no simple trick to have all the items know what the longest text item is, so a more complicated solution is required.
让所有项目都知道最长的文本项目不是简单的技巧,因此需要更复杂的解决方案。 The following works.
以下作品。 It will determine a fixed TextBlock size based on the largest item from the string list, and it will update it should the font size change.
它将基于字符串列表中的最大项确定固定的TextBlock大小,并且如果字体大小更改,它将更新该大小。 Obviously a simpler solution closer resembling your example code can be had if you decide on a fixed column size for either the text or the image, but I assume you already know that.
显然,如果您为文本或图像确定固定的列大小,则可以采用更类似于示例代码的简单解决方案,但是我想您已经知道了。
XAML: XAML:
<Page.DataContext>
<local:MainViewModel></local:MainViewModel>
</Page.DataContext>
<ListView ItemsSource="{Binding Items}">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding MyText, Mode=OneWay}" FontSize="{Binding ItemFontSize, Mode=OneWay}" Width="{Binding TextWidth, Mode=OneWay}" />
<Border Background="CornflowerBlue" Grid.Column="1" />
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
C# ViewModel C#ViewModel
public class MainViewModel : INotifyPropertyChanged
{
public ObservableCollection<MyListViewItemsClass> Items { get; set; }
private List<string> ItemsFromModel;
private int _myFontSize;
public int MyFontSize
{
get { return _myFontSize; }
set
{
if (value != _myFontSize)
{
_myFontSize = value;
OnPropertyChanged("MyFontSize");
// Font size changed, need to refresh ListView items
LoadRefreshMyListViewItems();
}
}
}
public MainViewModel()
{
// set default font size
_myFontSize = 20;
// example data
ItemsFromModel = new List<string>()
{
"ABC",
"ABCDEF",
"ABCDEFGHI",
};
LoadRefreshMyListViewItems();
}
public void LoadRefreshMyListViewItems()
{
int itemMaxTextLength = 0;
foreach (var modelItem in ItemsFromModel)
{
if (modelItem.Length > itemMaxTextLength) { itemMaxTextLength = modelItem.Length; }
}
Items = new ObservableCollection<MyListViewItemsClass>();
// Convert points to pixels, multiply by max character length to determine fixed textblock width
// This assumes 96 DPI. Search for how to grab system DPI in C# there are answers on SO.
double width = MyFontSize * 0.75 * itemMaxTextLength;
foreach (var itemFromModel in ItemsFromModel)
{
var item = new MyListViewItemsClass();
item.MyText = itemFromModel;
item.ItemFontSize = MyFontSize;
item.TextWidth = width;
Items.Add(item);
}
OnPropertyChanged("Items");
}
public class MyListViewItemsClass
{
public string MyText { get; set; }
public int ItemFontSize { get; set; }
public double TextWidth { get; set; }
}
protected void OnPropertyChanged(PropertyChangedEventArgs e)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
handler(this, e);
}
public void OnPropertyChanged(string propertyName)
{
OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
}
public event PropertyChangedEventHandler PropertyChanged;
}
Try setting ItemContainerStyle
property for the ListView: 尝试为ListView设置
ItemContainerStyle
属性:
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</ListView.ItemContainerStyle>
Then your ListView may look like this: 然后您的ListView可能如下所示:
<ListView x:Name="list">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock ... />
<Image Grid.Column="1" HorizontalAlignment="Right" ... />
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
After that, you can set a proper value for HorizontalAlignment
property of your ListView. 之后,可以为ListView的
HorizontalAlignment
属性设置适当的值。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.