I want to be able to maintain a list in the background that puts new items at the end of the list (to avoid Insert() pushing the items around on updates) but to be able to display it in the reverse order without "sorting".
I just want it to show up in the list view in the reverse order that it is in the list. Can I do this with a template or something similar?
You can change the ListView's ItemsPanel to be a DockPanel with LastChildFill set to false. Then in the ItemContainerStyle, set the DockPanel.Dock property to bottom. This will start filling at the bottom and work its way up to the top. I put the ListView in a grid with 2 rows, first's Height="Auto" and second's Height="*" and it acted just like a normal ListView, but with the items reversed.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<ListBox Grid.Row="0">
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}"
BasedOn="{StaticResource {x:Type ListBoxItem}}">
<Setter Property="DockPanel.Dock"
Value="Bottom" />
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<DockPanel LastChildFill="False" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
</Grid>
Idea taken from: https://stackoverflow.com/a/493059/2812277
Update
Here is an Attached Behavior which will reverse any ItemsControl
. Use it like this
<ListBox behaviors:ReverseItemsControlBehavior.ReverseItemsControl="True"
...>
ReverseItemsControlBehavior
public class ReverseItemsControlBehavior
{
public static DependencyProperty ReverseItemsControlProperty =
DependencyProperty.RegisterAttached("ReverseItemsControl",
typeof(bool),
typeof(ReverseItemsControlBehavior),
new FrameworkPropertyMetadata(false, OnReverseItemsControlChanged));
public static bool GetReverseItemsControl(DependencyObject obj)
{
return (bool)obj.GetValue(ReverseItemsControlProperty);
}
public static void SetReverseItemsControl(DependencyObject obj, object value)
{
obj.SetValue(ReverseItemsControlProperty, value);
}
private static void OnReverseItemsControlChanged(object sender, DependencyPropertyChangedEventArgs e)
{
if ((bool)e.NewValue == true)
{
ItemsControl itemsControl = sender as ItemsControl;
if (itemsControl.IsLoaded == true)
{
DoReverseItemsControl(itemsControl);
}
else
{
RoutedEventHandler loadedEventHandler = null;
loadedEventHandler = (object sender2, RoutedEventArgs e2) =>
{
itemsControl.Loaded -= loadedEventHandler;
DoReverseItemsControl(itemsControl);
};
itemsControl.Loaded += loadedEventHandler;
}
}
}
private static void DoReverseItemsControl(ItemsControl itemsControl)
{
Panel itemPanel = GetItemsPanel(itemsControl);
itemPanel.LayoutTransform = new ScaleTransform(1, -1);
Style itemContainerStyle;
if (itemsControl.ItemContainerStyle == null)
{
itemContainerStyle = new Style();
}
else
{
itemContainerStyle = CopyStyle(itemsControl.ItemContainerStyle);
}
Setter setter = new Setter();
setter.Property = ItemsControl.LayoutTransformProperty;
setter.Value = new ScaleTransform(1, -1);
itemContainerStyle.Setters.Add(setter);
itemsControl.ItemContainerStyle = itemContainerStyle;
}
private static Panel GetItemsPanel(ItemsControl itemsControl)
{
ItemsPresenter itemsPresenter = GetVisualChild<ItemsPresenter>(itemsControl);
if (itemsPresenter == null)
return null;
return GetVisualChild<Panel>(itemsControl);
}
private static Style CopyStyle(Style style)
{
Style styleCopy = new Style();
foreach (SetterBase currentSetter in style.Setters)
{
styleCopy.Setters.Add(currentSetter);
}
foreach (TriggerBase currentTrigger in style.Triggers)
{
styleCopy.Triggers.Add(currentTrigger);
}
return styleCopy;
}
private static T GetVisualChild<T>(DependencyObject parent) where T : Visual
{
T child = default(T);
int numVisuals = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < numVisuals; i++)
{
Visual v = (Visual)VisualTreeHelper.GetChild(parent, i);
child = v as T;
if (child == null)
{
child = GetVisualChild<T>(v);
}
if (child != null)
{
break;
}
}
return child;
}
}
Otherwise, you can follow what's outlined in the following link: WPF reverse ListView
<ListBox ...>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel VerticalAlignment="Top" Orientation="Vertical">
<VirtualizingStackPanel.LayoutTransform>
<ScaleTransform ScaleX="1" ScaleY="-1" />
</VirtualizingStackPanel.LayoutTransform>
</VirtualizingStackPanel>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="LayoutTransform">
<Setter.Value>
<ScaleTransform ScaleX="1" ScaleY="-1" />
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With