我有一个WPF应用程序,需要显示照片缩略图。通常有一张照片附在特定帖子上,但有时有两个,三,四个,但很少有。
如果一个帖子包含一张照片,我想显示一个大缩略图。如果包含两张照片,我想并排显示两个较小的照片。对于三张照片,我希望第一张很大,最后两张要显示在第一张照片下方,如果有四张照片,我想让它们在2x2网格中显示相同的大小。如果有四个以上,我想要一个小的省略号按钮,该按钮在底部显示有缩略图网格的全宽度,但高度很小。
这样的东西:
1 photo 2 photos 3 photos
|-----------| |-----------| |-----------|
| | | T | T | | |
| T | |-----------| | T |
| | | |
|-----------| |-----------|
| T | T |
|-----------|
4 photos 5 photos
|-----------| |-----------|
| T | T | | T | T |
|-----------| |-----------|
| T | T | | T | T |
|-----------| |-----------|
| ... |
|-----------|
在不创建5个不同的网格并根据照片数量的情况下切换其可见性的情况下,这是怎么可能的?我也使用MVVM,因此可以数据签名,这可能会使重要的事情变得复杂。
您可以使用不同的数据档案和自定义模板选择器,以决定基于给定模型中可用的图像数量使用的模板。您仍然需要单独声明网格,但是您不会触发所有网格的可见性,因为模板选择器只能返回适用于相应数字的图像数的模板。
编辑:添加示例和链接到源
以下是以下示例:https://msdn.microsoft.com/en-us/library/system.windows.controls.contentcontrol.contenttemplateselector(v = vs.110(.aspx
它显示了如何使用自定义DataTemplateSelector
根据SelectTemplate(object item, DependencyObject container)
中的给定参数返回合适的模板。
xaml:
<Window.Resources>
<!--Create two DataTemplate objects to be
selected by the DataTemplateSelector.-->
<DataTemplate x:Key="numberTemplate">
<Grid>
<Rectangle Stroke="Black" />
<TextBlock Margin="5" Text="{Binding}" FontSize="18"/>
</Grid>
</DataTemplate>
<DataTemplate x:Key="largeNumberTemplate">
<Grid>
<Ellipse Stroke="Green" StrokeThickness="4"/>
<TextBlock Margin="10" Text="{Binding}" FontSize="24"
Foreground="Red" FontWeight="Bold" />
</Grid>
</DataTemplate>
<local:NumderDataTemplateSelector x:Key="numberTemplateSelector"/>
</Window.Resources>
<StackPanel>
<!--Bind the content of the Label to the selected item
in the ComboBox.-->
<Label Foreground="Black"
Content="{Binding ElementName=numberList, Path=SelectedItem.Content}"
ContentTemplateSelector="{StaticResource numberTemplateSelector}">
</Label>
<ComboBox Name="numberList">
<ComboBoxItem>1</ComboBoxItem>
<ComboBoxItem>2</ComboBoxItem>
<ComboBoxItem>3</ComboBoxItem>
<ComboBoxItem>4</ComboBoxItem>
<ComboBoxItem>5</ComboBoxItem>
<ComboBoxItem>6</ComboBoxItem>
<ComboBoxItem IsSelected="True">7</ComboBoxItem>
<ComboBoxItem>8</ComboBoxItem>
<ComboBoxItem>9</ComboBoxItem>
<ComboBoxItem>10</ComboBoxItem>
</ComboBox>
</StackPanel>
C#中的模板运行仪:
public class NumderDataTemplateSelector : DataTemplateSelector
{
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
string numberStr = item as string;
if (numberStr != null)
{
int num;
Window win = Application.Current.MainWindow;
try
{
num = Convert.ToInt32(numberStr);
}
catch
{
return null;
}
// Select one of the DataTemplate objects, based on the
// value of the selected item in the ComboBox.
if (num < 5)
{
return win.FindResource("numberTemplate") as DataTemplate;
}
else
{
return win.FindResource("largeNumberTemplate") as DataTemplate;
}
}
return null;
}
}
不确定一种绑定方法,因为我想您需要编写自己的控件,以正确地获取此功能。
我建议使用自定义控件(也许是tookspresenter的衍生物(,我把这个基本的linqpad片段扔了在一起:
void Main()
{
var window = new Window();
var photos = new[] {
"http://www.cats.org.uk/uploads/images/featurebox_sidebar_kids/grief-and-loss.jpg",
"http://www.rd.com/wp-content/uploads/sites/2/2016/04/01-cat-wants-to-tell-you-laptop.jpg",
"https://media2.giphy.com/media/yAqdjThdDEMF2/200_s.gif",
"https://i.ytimg.com/vi/cNycdfFEgBc/maxresdefault.jpg",
"http://r.ddmcdn.com/s_f/o_1/cx_462/cy_245/cw_1349/ch_1349/w_720/APL/uploads/2015/06/caturday-shutterstock_149320799.jpg"
};
var grid = BuildGrid(photos);
window.Content = grid;
window.Show();
}
// Define other methods and classes here
Tuple<int, int, int, int> GetItemPosition(int pos, int count)
{
if (count == 1)
{
return Tuple.Create(0, 2, 0, 4);
}
if (count == 2)
{
if (pos == 1) return Tuple.Create(0, 0, 0, 0);
if (pos == 2) return Tuple.Create(0, 0, 1, 0);
}
if (count == 3)
{
if (pos == 1) return Tuple.Create(0, 0, 0, 2);
if (pos == 2) return Tuple.Create(1, 0, 0, 0);
if (pos == 3) return Tuple.Create(1, 0, 1, 0);
}
if (count == 4)
{
if (pos == 1) return Tuple.Create(0, 0, 0, 0);
if (pos == 2) return Tuple.Create(0, 0, 1, 0);
if (pos == 3) return Tuple.Create(1, 0, 0, 0);
if (pos == 4) return Tuple.Create(1, 0, 1, 0);
}
if (count == 5)
{
if (pos == 1) return Tuple.Create(0, 0, 0, 0);
if (pos == 2) return Tuple.Create(0, 0, 1, 0);
if (pos == 3) return Tuple.Create(1, 0, 0, 0);
if (pos == 4) return Tuple.Create(1, 0, 1, 0);
if (pos == 5) return Tuple.Create(3, 0, 0,2);
}
return null;
}
Grid BuildGrid(string[] photos)
{
var grid = new Grid();
grid.HorizontalAlignment = HorizontalAlignment.Center;
grid.VerticalAlignment = VerticalAlignment.Center;
var fillLength = new GridLength(1, GridUnitType.Star);
for (var col = 0; col < 2; col++)
{
grid.ColumnDefinitions.Add(new ColumnDefinition { Width = fillLength });
}
for (var row = 0; row < 4; row++)
{
grid.RowDefinitions.Add(new RowDefinition { Height = fillLength });
}
for (var idx = 0; idx < photos.Length; idx++)
{
var img = new Image();
img.Margin = new Thickness(10);
var bi = new BitmapImage();
bi.BeginInit();
bi.UriSource = new Uri( photos[idx], UriKind.Absolute);
bi.EndInit();
img.Source = bi;
img.HorizontalAlignment = HorizontalAlignment.Center;
img.VerticalAlignment = VerticalAlignment.Center;
var pos = GetItemPosition(idx + 1, photos.Length);
pos.Dump();
if (pos == null) continue;
img.SetValue(Grid.RowProperty, pos.Item1);
img.SetValue(Grid.RowSpanProperty, pos.Item2 == 0 ? 1 : pos.Item2);
img.SetValue(Grid.ColumnProperty, pos.Item3);
img.SetValue(Grid.ColumnSpanProperty, pos.Item4 == 0 ? 1 : pos.Item4);
grid.Children.Add(img);
}
return grid;
}
这绝不是完美的,但它显示了您如何做到这一点的粗略基础。
也没有实施5个项目后显示椭圆形和切断的行为,但不应该实现。