Этот ответ превратился в монстра, но сильный удар через него, и я думаю, что вы будете найти ответ.
Нам необходимо каким-то образом использовать VirtualizingStackPanel
как ListBox
. Нам нужно собрать все элементы для отображения (кнопка, два текстовых блока и два набора городских данных) в один перечислимый какой-либо тип. Настоящий трюк и будет определять один из трех шаблонов, используемых для рендеринга элементов.
Подводя итог, мы должны создать новый тип ItemsControl
. Теперь мы можем получить небольшое преимущество, просто согласившись с тем, что хотим создать очень специфичный ItemsControl
, который поддерживает только эту задачу. Сначала это «стартер на 10» (ссылка в Великобритании).
Действительно тупой пример создания определенных элементов управления: -
public class SwitchingItemsControl : ItemsControl
{
public DataTemplate AlternativeItemTemplate { get; set; }
protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
{
ContentPresenter cp = (ContentPresenter)element;
if (AlternativeItemTemplate != null && (((int)item) & 1) == 1)
cp.ContentTemplate = AlternativeItemTemplate;
else
cp.ContentTemplate = ItemTemplate;
cp.Content = item;
}
}
Этот контроль предполагает его элементы представляют собой набор целых чисел. У него есть AlternativeItemTemplate
, который, если он поставляется, переключается между ними на нечетной/четной основе (обратите внимание, что это грань элемента).
Теперь давайте положить, что использование с VirtualizingStackPanel
: -
<UserControl x:Class="CustomVirtualizingPanelInSL.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:SilverlightApplication1"
Width="400" Height="300">
<Grid x:Name="LayoutRoot" Background="White">
<local:SwitchingItemsControl x:Name="itemsControl" >
<local:SwitchingItemsControl.Template>
<ControlTemplate TargetType="local:SwitchingItemsControl">
<ScrollViewer VerticalScrollBarVisibility="Visible">
<ItemsPresenter />
</ScrollViewer>
</ControlTemplate>
</local:SwitchingItemsControl.Template>
<local:SwitchingItemsControl.ItemTemplate>
<DataTemplate>
<Border CornerRadius="2" BorderBrush="Blue" BorderThickness="1" Margin="2">
<TextBlock VerticalAlignment="Center" HorizontalAlignment="Center" Text="{Binding}" />
</Border>
</DataTemplate>
</local:SwitchingItemsControl.ItemTemplate>
<local:SwitchingItemsControl.AlternativeItemTemplate>
<DataTemplate>
<Border CornerRadius="2" BorderBrush="Red" BorderThickness="1" Margin="2">
<TextBlock VerticalAlignment="Center" HorizontalAlignment="Center" Text="{Binding}" />
</Border>
</DataTemplate>
</local:SwitchingItemsControl.AlternativeItemTemplate>
<local:SwitchingItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel />
</ItemsPanelTemplate>
</local:SwitchingItemsControl.ItemsPanel>
</local:SwitchingItemsControl>
</Grid>
</UserControl>
Обратите внимание на ItemsPanel
использующем VirtualizingStackPanel
и получает представленный в ScrollViewer
.
Теперь мы можем дать ему много содержания: -
namespace SilverlightApplication1
{
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
itemsControl.ItemsSource = Enumerable.Range(0, 10000);
}
}
}
Если переключиться на стандартный StackPanel
это принимает возрастов для загрузки, в то время как он появляется мгновенная с виртуализацией.
Вооруженный этой информацией, вы должны быть в состоянии создать специальный ItemsControl, который обладает свойствами: -
- ButtonTemplate (DataTemplate)
- HeaderTemplate (DataTemplate)
- TopTenHeaderText (String)
- TopHundredHeaderText (String)
- TopTenSource (
IEnumerable<City>
)
- Ti pHunderedSource (
IEnumerable<City>
)
Теперь вы можете создать единый перечислимы с некоторыми методами расширения Linq: -
itemsControl.ItemsSource = Enumerable.Repeat((object)null, 1)
.Concat(Enumerable.Repeat((object)TopTenHeadeText))
.Concat(TopTenSource.Cast<object>())
.Concat(Enumerable.Repeat((object)TopHundredText))
.Concat(TopHundredSource.Cast<object>())
Теперь вам просто нужно переопределить PrepareContainerForItemOverride
и выбирать между ButtonTemplate
(для первого элемента нуль), HeaderTemplate
для элемента типа string или ItemTemplate
для элемента типа City
.
Быстрые наблюдения ... являются ли списки однородными (они обертывают один и тот же тип элементов?) Если нет, являются ли элементы, полученные из любого общего базового класса (кроме System.Object)? Должны ли содержимое списков быть представлены по-разному в зависимости от того, из какого списка они пришли? – avidgator
Это те же самые типы элементов, и я использую один и тот же шаблон ... но мне нужен этот заголовок между ними, таким образом, разделение на слое пользовательского интерфейса, а не перегруппировка на уровне модели представления. –