动态网格中的照片缩略图



我有一个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个项目后显示椭圆形和切断的行为,但不应该实现。

最新更新