2014-11-04 2 views
1

Я ищу способ сделать пользовательский список для Windows Phone 7.1, например, карты google now. Эффект прост: два столбца. Следующая карта будет максимально возможной.Пользовательский список карточек, как google now

Если в колонке 1 100px высокий и столбец 2 составляет 170 точек, то следующая карта будет в колонке 1.

enter image description here

Я попытался WrapPanel но выравнивает верхнюю часть каждой строки. Таким образом, опция состоит в том, чтобы создать пользовательский список (или получить уже выполненный). Obviusly, я не могу сделать «бесконечное» представление и добавлять к нему взгляды, но я думаю, что это будет не очень эффективно.

Спасибо!

ответ

3

я добавлю еще один ответ, так как код изменен:

public class ViewModel : INotifyPropertyChanged 
{ 
    private Random rnd = new Random(DateTime.Now.Millisecond); 

    public ViewModel() 
    { 
     Items = new List<DataItem>() 
        { 
         new DataItem() 
          { 
           Title = "Title 1", 
           Height = rnd.Next(100, 250), 
           Color = new SolidColorBrush(Colors.Green), 
           Content = 
            "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque non bibendum nisi. Aenean eu elementum massa. Praesent vel urna id neque tristique maximus." 
          }, 
         new DataItem() 
          { 
           Title = "Title 2", 
           Height = rnd.Next(100, 250), 
           Color = new SolidColorBrush(Colors.Blue), 
           Content = 
            "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque non bibendum nisi. Aenean eu elementum massa. Praesent vel urna id neque tristique maximus." 
          }, 
         new DataItem() 
          { 
           Title = "Title 3", 
           Height = rnd.Next(100, 250), 
           Color = new SolidColorBrush(Colors.Purple), 
           Content = 
            "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque non bibendum nisi. Aenean eu elementum massa. Praesent vel urna id neque tristique maximus." 
          }, 
         new DataItem() 
          { 
           Title = "Title 4", 
           Height = rnd.Next(100, 250), 
           Color = new SolidColorBrush(Colors.Brown), 
           Content = 
            "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque non bibendum nisi. Aenean eu elementum massa. Praesent vel urna id neque tristique maximus." 
          }, 
         new DataItem() 
          { 
           Title = "Title 5", 
           Height = rnd.Next(100, 250), 
           Color = new SolidColorBrush(Colors.Gray), 
           Content = 
            "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque non bibendum nisi. Aenean eu elementum massa. Praesent vel urna id neque tristique maximus." 
          }, 
         new DataItem() 
          { 
           Title = "Title 6", 
           Height = rnd.Next(100, 250), 
           Color = new SolidColorBrush(Colors.Green), 
           Content = 
            "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque non bibendum nisi. Aenean eu elementum massa. Praesent vel urna id neque tristique maximus." 
          }, 
         new DataItem() 
          { 
           Title = "Title 7", 
           Height = rnd.Next(100, 250), 
           Color = new SolidColorBrush(Colors.Brown), 
           Content = 
            "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque non bibendum nisi. Aenean eu elementum massa. Praesent vel urna id neque tristique maximus." 
          }, 
         new DataItem() 
          { 
           Title = "Title 8", 
           Height = rnd.Next(100, 250), 
           Color = new SolidColorBrush(Colors.Magenta), 
           Content = 
            "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque non bibendum nisi. Aenean eu elementum massa. Praesent vel urna id neque tristique maximus." 
          }, 
         new DataItem() 
          { 
           Title = "Title 9", 
           Height = rnd.Next(100, 250), 
           Color = new SolidColorBrush(Colors.Orange), 
           Content = 
            "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque non bibendum nisi. Aenean eu elementum massa. Praesent vel urna id neque tristique maximus." 
          }, 
         new DataItem() 
          { 
           Title = "Title 10", 
           Height = rnd.Next(100, 250), 
           Color = new SolidColorBrush(Colors.Purple), 
           Content = 
            "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque non bibendum nisi. Aenean eu elementum massa. Praesent vel urna id neque tristique maximus." 
          }, 
         new DataItem() 
          { 
           Title = "Title 11", 
           Height = rnd.Next(100, 250), 
           Color = new SolidColorBrush(Colors.Brown), 
           Content = 
            "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque non bibendum nisi. Aenean eu elementum massa. Praesent vel urna id neque tristique maximus." 
          }, 
         new DataItem() 
          { 
           Title = "Title 12", 
           Height = rnd.Next(100, 250), 
           Color = new SolidColorBrush(Colors.Red), 
           Content = 
            "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque non bibendum nisi. Aenean eu elementum massa. Praesent vel urna id neque tristique maximus." 
          }, 
        }; 
    } 

    public List<DataItem> Items 
    { 
     set 
     { 
      int List1Height = 0; 
      int List2Height = 1; // set to 1 so first item will end up in List1 
      Items1 = new List<DataItem>(); 
      Items2 = new List<DataItem>(); 
      foreach (DataItem dataItem in value) 
      { 
       if (List1Height < List2Height) 
       { 
        Items1.Add(dataItem); 
        List1Height += dataItem.Height; 
       } 
       else 
       { 
        Items2.Add(dataItem); 
        List2Height += dataItem.Height; 
       } 
      } 
     } 
    } 

    private List<DataItem> _items1; 

    public List<DataItem> Items1 
    { 
     get { return _items1; } 
     set 
     { 
      _items1 = value; 
      OnPropertyChanged("Items1"); 
     } 
    } 

    private List<DataItem> _items2; 

    public List<DataItem> Items2 
    { 
     get { return _items2; } 
     set 
     { 
      _items2 = value; 
      OnPropertyChanged("Items2"); 
     } 
    } 



    public event PropertyChangedEventHandler PropertyChanged; 

    protected virtual void OnPropertyChanged(string propertyName) 
    { 
     PropertyChangedEventHandler handler = PropertyChanged; 
     if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName)); 
    } 
} 

public class DataItem 
{ 
    public string Title { get; set; } 
    public int Height { get; set; } 
    public SolidColorBrush Color { get; set; } 
    public string Content { get; set; } 
} 

Самым значительным изменением является добавление свойства под названием «Элементы». Когда это свойство установлено, элементы добавляются в один из двух списков, в зависимости от того, какой из них короче в момент добавления элемента. Нет никакого геттера, поскольку мы не привязаны к этому свойству.

Я также добавил некоторую цветовую и случайную высоту для целей тестирования, немного очистил XAML, чтобы сделать содержимое более четким, а также добавлена ​​поддержка INotifyPropertyChanged, поэтому когда свойство Items установлено и добавляет элементы в 2 списка, пользовательский интерфейс будет обновляться автоматически.

<!--ContentPanel - place additional content here--> 
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> 
    <ScrollViewer Margin="10"> 
     <StackPanel Orientation="Horizontal" > 
      <StackPanel Orientation="Vertical" Width="210"> 
       <ItemsControl ItemsSource="{Binding Items1}"> 
        <ItemsControl.ItemTemplate> 
         <DataTemplate> 
          <Grid Height="{Binding Height}" Margin="5" Background="{Binding Color}" > 
           <Grid.RowDefinitions> 
            <RowDefinition Height="50"/> 
            <RowDefinition Height="1*"/> 
           </Grid.RowDefinitions> 
           <TextBlock Text="{Binding Title}" Grid.Row="0" Style="{StaticResource PhoneTextLargeStyle}"/> 
           <TextBlock Text="{Binding Content}" Grid.Row="1" TextWrapping="Wrap" Margin="5"/> 
          </Grid> 
         </DataTemplate> 
        </ItemsControl.ItemTemplate> 
       </ItemsControl > 
      </StackPanel> 
      <StackPanel Orientation="Vertical" Width="210"> 
       <ItemsControl ItemsSource="{Binding Items2}"> 
        <ItemsControl.ItemTemplate> 
         <DataTemplate> 
          <Grid Height="{Binding Height}" Margin="5" Background="{Binding Color}" > 
           <Grid.RowDefinitions> 
            <RowDefinition Height="50"/> 
            <RowDefinition Height="1*"/> 
           </Grid.RowDefinitions> 
           <TextBlock Text="{Binding Title}" Grid.Row="0" Style="{StaticResource PhoneTextLargeStyle}"/> 
           <TextBlock Text="{Binding Content}" Grid.Row="1" TextWrapping="Wrap" Margin="5"/> 
          </Grid> 
         </DataTemplate> 
        </ItemsControl.ItemTemplate> 
       </ItemsControl> 
      </StackPanel> 
     </StackPanel> 
    </ScrollViewer> 
</Grid> 

Извещение о пунктах 3-6 и о том, как 4 и 5 складываются вместе в одной колонке. Notice items 3-6 and how 4 and 5 are stacked together in the same column.

Я понимаю, что мой ответ не соответствует вашей потребности в едином автоматическом способе подачи предметов в один из двух столбцов. однако он, похоже, удовлетворяет желаемому результату: список прокрутки в 2 столбца, в котором элементы попадают в самый короткий столбец.

Следующий шаг для вас, если вы действительно нуждаетесь в нем в качестве элемента управления, состоит в том, чтобы сделать его либо в UserControl, либо в CustomControl. Какой из них зависит от ваших навыков и объема работы, которую вы готовы вложить в нее.

Хорошее сравнение-можно найти здесь: http://www.geekchamp.com/articles/user-control-vs-custom-control-in-silverlight-for-wp7

+0

Большое вам спасибо, кажется, это то, что мне нужно! –

+0

Рад помочь! :) Я не отдал много внимания сообществу, так как была опубликована книга, в которую я внес свой вклад. Просто счастлив вернуть всю помощь, которую я получил за эти годы. –

+0

Я боюсь, но это может вызвать проблемы ... Я использую фотографии внутри карт, поэтому у меня есть outofmemoryexception, если есть много карт :( –

0

Вы должны использовать ScrollViewer с некоторыми StackPanels внутри:

<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> 
    <ScrollViewer Margin="10"> 
     <StackPanel Orientation="Horizontal"> 
      <StackPanel Orientation="Vertical" Width="210"> 
       <Grid Height="200" Margin="5" Background="Blue" /> 
       <Grid Height="200" Margin="5" Background="Blue" /> 
       <Grid Height="200" Margin="5" Background="Blue" /> 
       <Grid Height="200" Margin="5" Background="Blue" /> 
       <Grid Height="200" Margin="5" Background="Blue" /> 
      </StackPanel> 
      <StackPanel Orientation="Vertical" Width="210"> 
       <Grid Height="300" Margin="5" Background="Blue" /> 
       <Grid Height="300" Margin="5" Background="Blue" /> 
       <Grid Height="300" Margin="5" Background="Blue" /> 
       <Grid Height="300" Margin="5" Background="Blue" /> 
      </StackPanel> 
     </StackPanel> 
    </ScrollViewer> 
</Grid> 

Вы, скорее всего, положить что-то внутри внутренние панели стеки (вместо Сетки я использовал в качестве образца), чтобы привязывать элементы данных шаблон, но перечисленное решение ScrollViewer/StackPanel поможет вам начать работу в правильном направлении.

2

Вот пример использования привязки данных к модели просмотра. Он использует ItemsPanel укладывать элементы в горизонтальной StackPanel:

Код За:

using System.Collections.Generic; 
using Microsoft.Phone.Controls; 

namespace PhoneApp1 
{ 
    public partial class MainPage : PhoneApplicationPage 
    { 
     // Constructor 
     public MainPage() 
     { 
      InitializeComponent(); 

     } 

     public ViewModel ViewModel { get; set; } 
     protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e) 
     { 
      base.OnNavigatedTo(e); 
      ViewModel = new ViewModel(); 
      DataContext = ViewModel; 
     } 


    } 
    public class ViewModel 
    { 
     public ViewModel() 
     { 
      Items1 = new List<DataItem>() 
         { 
          new DataItem(){Title = "Title", Content = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque non bibendum nisi. Aenean eu elementum massa. Praesent vel urna id neque tristique maximus."}, 
          new DataItem(){Title = "Title", Content = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque non bibendum nisi. Aenean eu elementum massa. Praesent vel urna id neque tristique maximus."}, 
          new DataItem(){Title = "Title", Content = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque non bibendum nisi. Aenean eu elementum massa. Praesent vel urna id neque tristique maximus."}, 
          new DataItem(){Title = "Title", Content = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque non bibendum nisi. Aenean eu elementum massa. Praesent vel urna id neque tristique maximus."}, 
          new DataItem(){Title = "Title", Content = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque non bibendum nisi. Aenean eu elementum massa. Praesent vel urna id neque tristique maximus."}, 
          new DataItem(){Title = "Title", Content = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque non bibendum nisi. Aenean eu elementum massa. Praesent vel urna id neque tristique maximus."}, 
         }; 

      Items2 = new List<DataItem>() 
         { 
          new DataItem(){Title = "Title", Content = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque non bibendum nisi. Aenean eu elementum massa. Praesent vel urna id neque tristique maximus."}, 
          new DataItem(){Title = "Title", Content = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque non bibendum nisi. Aenean eu elementum massa. Praesent vel urna id neque tristique maximus."}, 
          new DataItem(){Title = "Title", Content = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque non bibendum nisi. Aenean eu elementum massa. Praesent vel urna id neque tristique maximus."}, 
          new DataItem(){Title = "Title", Content = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque non bibendum nisi. Aenean eu elementum massa. Praesent vel urna id neque tristique maximus."}, 
          new DataItem(){Title = "Title", Content = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque non bibendum nisi. Aenean eu elementum massa. Praesent vel urna id neque tristique maximus."}, 
          new DataItem(){Title = "Title", Content = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque non bibendum nisi. Aenean eu elementum massa. Praesent vel urna id neque tristique maximus."}, 
         }; 
     } 
     public List<DataItem> Items1 { get; set; } 
     public List<DataItem> Items2 { get; set; } 
    } 
    public class DataItem 
    { 
     public string Title { get; set; } 
     public string Content { get; set; } 
    } 
} 

И фактической XAML:

<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> 

     <ScrollViewer Margin="10"> 
      <StackPanel Orientation="Horizontal" > 
       <StackPanel Orientation="Vertical" Width="210"> 
        <ItemsControl ItemsSource="{Binding Items1}"> 
         <ItemsControl.ItemTemplate> 
          <DataTemplate> 
           <Grid Height="333" Margin="5" Background="Red" > 
            <Grid.RowDefinitions> 
             <RowDefinition Height="50"/> 
             <RowDefinition Height="1*"/> 
            </Grid.RowDefinitions> 
            <TextBlock Text="{Binding Title}" Grid.Row="0"/> 
            <TextBlock Text="{Binding Content}" Grid.Row="1" TextWrapping="Wrap"/> 
           </Grid> 
          </DataTemplate> 
         </ItemsControl.ItemTemplate> 
        </ItemsControl > 
       </StackPanel> 
       <StackPanel Orientation="Vertical" Width="210"> 
        <ItemsControl ItemsSource="{Binding Items2}"> 
         <ItemsControl.ItemTemplate> 
          <DataTemplate> 
           <Grid Height="200" Margin="5" Background="Blue" > 
            <Grid.RowDefinitions> 
             <RowDefinition Height="50"/> 
             <RowDefinition Height="1*"/> 
            </Grid.RowDefinitions> 
            <TextBlock Text="{Binding Title}" Grid.Row="0"/> 
            <TextBlock Text="{Binding Content}" Grid.Row="1" TextWrapping="Wrap"/> 
           </Grid> 
          </DataTemplate> 
         </ItemsControl.ItemTemplate> 
        </ItemsControl> 
       </StackPanel> 
      </StackPanel> 
     </ScrollViewer> 
    </Grid> 

Resulting scrolling 2-column list

+0

Спасибо, но мне нужен один список и присвоить каждый элемент столбец 1 или 2 относительно предыдущей высоты элементов. –

+1

Это не сложно, если вы знаете высоту, если каждый элемент. Просто пройдите по элементам, отслеживая общую высоту, если каждый столбец и добавьте элемент в зависимости от того, какая колонка короче по высоте. Позвольте мне начать работать, и я создам быстрый пример. –

+1

Как только поведение будет таким, как вам нравится, его можно перенести в пользовательский элемент управления. Тогда вы даже не увидите пару списков, используемых для его вождения. :) –

Смежные вопросы