我正在寻找一种方法来为Windows Phone 7.1做一个自定义列表框,就像google now cards一样。效果很简单:两列。下一张卡将尽可能顶。
如果第1列为100px高,第2列为170像素,则下一张卡将在第1列。
我尝试了WrapPanel,但它对齐了每一行的顶部。所以选项是构建一个自定义列表框(或者已经完成一个)。可怜的是,我无法做出一个无限的'查看并添加视图,但我想这不会非常有效。
谢谢!
答案 0 :(得分: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; }
}
最重要的变化是添加一个名为“Items”的属性。设置此属性后,项目将添加到两个列表中的一个列表中,具体取决于添加项目时哪个项目更短。没有吸气剂,因为我们没有约束这个属性。
我还添加了一些颜色和随机高度用于测试目的,清理了一些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如何在同一列中堆叠在一起。
我意识到我的答案无法满足您对单个自动方式将项目流入2列之一的需求。但是,它似乎满足了所需的结果:2列滚动列表,其中项目流入最短列。
如果您真的需要它作为控件,那么下一步就是将它变成UserControl或CustomControl。哪一项取决于您的技能和您愿意投入的工作量。
可以在此处找到2的良好比较:http://www.geekchamp.com/articles/user-control-vs-custom-control-in-silverlight-for-wp7
答案 1 :(得分:2)
以下是使用数据绑定到viewmodel的示例。它使用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>
答案 2 :(得分:0)
你应该在里面使用带有一些StackPanels的ScrollViewer:
<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解决方案将使您从正确的方向开始