我有一个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进行数据绑定,这可能使问题复杂化。
答案 0 :(得分:1)
您可以使用不同的DataTemplates和自定义模板选择器,根据给定模型中可用的图像数量决定使用哪个模板。您仍然需要单独声明网格,但不会触发所有网格的可见性,因为模板选择器只会返回适用于相应数量图像的模板。
编辑:添加示例并链接到源
的示例它显示了如何使用自定义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#中的TemplateSelector:
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;
}
}
答案 1 :(得分:0)
不确定绑定方法,因为我认为您需要编写自己的控件以正确地获取此方式,而您不依赖于显示/隐藏多个网格。
我建议使用自定义控件(也许是ItemsPresenter的衍生产品),并且我将这个基本的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个项目之后显示椭圆和切断的行为也没有实现,但是不应该太难实现。