Я создал ListView с подробным элементом expad, я установил ItemsPanelTemplate на ElasticWrapPanel.см. рис. Мне нужно посоветовать, как переделать ElasticWrapPanel на ElasticVirtualizingWrapPanel.
Я пробовал VirtualizingTilePanel, но не вижу развернутого элемента детализации, см. рисунок 2. Кто-нибудь посоветует мне.Спасибо за ответ.
ListView с ElasticWrapPanel
ListView с VirtualizingTilePanel
пример исходного кода
ListView XAML:
<ListView ItemsSource="{Binding}" DataContext="ABCDEFGHIJKLMNOPQRSTUVWXYZ">
<ListView.Resources>
<DataTemplate x:Key="DetailTempalte">
<Grid Height="100" Background="Green" Margin="5">
<Button Content="{Binding}" HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>
</DataTemplate>
<ControlTemplate TargetType="{x:Type ListViewItem}" x:Key="withDetailTemplate">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Border Grid.Row="0" x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="true">
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Border>
<!-- **************** -->
<Canvas Grid.Row="1" x:Name="detailCanvas"
Width="0"
Height="{Binding ElementName=detailGrid,Path=ActualHeight}"
HorizontalAlignment="Left" VerticalAlignment="Top" Visibility="Collapsed">
<Grid x:Name="detailGrid" Width="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type ScrollContentPresenter}},Path=ActualWidth}"
Canvas.Left="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type ListViewItem}},Path=(local:ElasticWrapPanel .ItemLocation).LocationN.X}">
<ContentPresenter ContentTemplate="{DynamicResource ResourceKey=DetailTempalte}" />
</Grid>
</Canvas>
<!-- **************** -->
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="true">
<Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}"/>
<Setter TargetName="detailCanvas" Property="Visibility" Value="Visible"/>
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsSelected" Value="true"/>
<Condition Property="Selector.IsSelectionActive" Value="false"/>
</MultiTrigger.Conditions>
<Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.InactiveSelectionHighlightBrushKey}}"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.InactiveSelectionHighlightTextBrushKey}}"/>
</MultiTrigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</ListView.Resources>
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="Template" Value="{StaticResource withDetailTemplate}" />
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<local:WrapPaneEx Width="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type ScrollContentPresenter}},Path=ActualWidth}"/>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemTemplate>
<DataTemplate>
<Grid Width="100" Height="100" Background="Blue" Margin="5">
<TextBlock Text="{Binding}" Foreground="White" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
ElasticWrapPanel без виртуализации:
public class ElasticWrapPanel : Panel
{
#region Constructor
public ElasticWrapPanel()
{
}
#endregion
#region Properties
[TypeConverter(typeof(LengthConverter))]
public double ItemMinWidth
{
get
{
return (double)GetValue(ItemMinWidthProperty);
}
set
{
SetValue(ItemMinWidthProperty, value);
}
}
public static readonly DependencyProperty ItemMinWidthProperty = DependencyProperty.Register("ItemMinWidth", typeof(double), typeof(ElasticWrapPanel));
[TypeConverter(typeof(LengthConverter))]
public double ColumnWidth
{
get
{
return (double)GetValue(ColumnWidthProperty);
}
private set
{
SetValue(ColumnWidthProperty, value);
}
}
public static readonly DependencyProperty ColumnWidthProperty = DependencyProperty.Register("ColumnWidth", typeof(double), typeof(ElasticWrapPanel));
#endregion
#region Protected methods
protected override Size MeasureOverride(Size availableSize)
{
_uiElementsRect.Clear();
_columnCount = CalculateColumnCount(availableSize);
if (_columnCount > 0)
{
ColumnWidth = (int)Math.Floor(availableSize.Width / _columnCount);
double rowHeight = 0;
double lastRowHeight = 0;
int currentColumn = 0;
int currentRow = 0;
foreach (UIElement children in InternalChildren)
{
children.Measure(availableSize);
((FrameworkElement)children).MaxWidth = ColumnWidth;
var itemLocation = GetItemLocation(children);
if (itemLocation == null)
{
itemLocation = new ItemLocation(this, children);
SetItemLocation(children, itemLocation);
}
itemLocation.OnLocationPropertyChanged();
children.Measure(availableSize);
rowHeight = Math.Max(rowHeight, children.DesiredSize.Height);
Rect childrenRect = new Rect(0, 0, 0, 0);
childrenRect.X = currentColumn * ColumnWidth;
childrenRect.Y = lastRowHeight;
childrenRect.Width = ColumnWidth;
childrenRect.Height = children.DesiredSize.Height;
_uiElementsRect.Add(children, childrenRect);
currentColumn++;
if (currentColumn == _columnCount)
{
lastRowHeight += rowHeight;
currentRow++;
rowHeight = 0;
currentColumn = 0;
}
}
}
if (_uiElementsRect.Any())
{
double maxBottom = _uiElementsRect.Max(ui => ui.Value.Bottom);
return new Size(availableSize.Width, maxBottom);
}
else
return base.MeasureOverride(availableSize);
}
protected override Size ArrangeOverride(Size finalSize)
{
if (_columnCount > 0)
foreach (KeyValuePair<UIElement, Rect> keyValuePair in _uiElementsRect)
keyValuePair.Key.Arrange(keyValuePair.Value);
return base.ArrangeOverride(finalSize);
}
#endregion
#region Private methods
private int CalculateColumnCount(Size availableSize)
{
if (ItemMinWidth == 0 || Double.IsNaN(ItemMinWidth) || Double.IsInfinity(availableSize.Width))
return 0;
else
return (int)Math.Floor(availableSize.Width / ItemMinWidth);
}
#endregion
#region Private members
int _columnCount = 0;
IDictionary<UIElement, Rect> _uiElementsRect = new Dictionary<UIElement, Rect>();
#endregion
public static ItemLocation GetItemLocation(DependencyObject obj)
{
return (ItemLocation)obj.GetValue(ItemLocationProperty);
}
public static void SetItemLocation(DependencyObject obj, ItemLocation value)
{
obj.SetValue(ItemLocationProperty, value);
}
public static readonly DependencyProperty ItemLocationProperty = DependencyProperty.RegisterAttached("ItemLocation", typeof(ItemLocation), typeof(ElasticWrapPanel), new PropertyMetadata(null));
}
public class ItemLocation : System.ComponentModel.INotifyPropertyChanged
{
public ItemLocation(Panel panel, UIElement itemContainer)
{
this._Panel = panel;
this._ItemContainer = itemContainer;
}
private UIElement _ItemContainer;
private Panel _Panel;
public Point? Location
{
get
{
if (_Location == null && _Panel != null && _ItemContainer != null)
{
_Location = _ItemContainer.TranslatePoint(default(Point), _Panel);
}
return _Location;
}
}
private Point? _Location;
public Point? LocationN
{
get
{
if (_LocationN == null && _Location == null && _Panel != null && _ItemContainer != null)
{
Point? np = Location;
if (np != null)
{
_LocationN = new Point(-np.Value.X, -np.Value.Y);
}
}
return _LocationN;
}
}
private Point? _LocationN;
public event PropertyChangedEventHandler PropertyChanged;
internal void OnLocationPropertyChanged()
{
_Location = null;
_LocationN = null;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Location)));
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(LocationN)));
}
}
VirtualizingTilePanel без детализации развернуть элемент https://gist.github.com/ORRNY66/7bda3087f9758b892f33c5ceccfb84b8