I spent last two weeks trying to figure out a method to display the items of a listbox in reversed order without using any sort property and without putting any presentation logic in my entities, I just want that the last inserted item is displayed at the top of the listbox. The only pure XAML solution I've found is this WPF reverse ListView but it isn't so elegant. I've also tried to override the GetEnumerator() of my BindableCollection (I use Caliburn Micro as MVVM framework) to return an enumerator that iterate over my collection's items in the reverse order but id did not work. How can I do?
Asked
Active
Viewed 2,709 times
2
-
I think the ScaleTransform solution is elegant. – paparazzo Sep 13 '11 at 19:13
-
do you think is the right solution for this problem? – Gigitsu Sep 13 '11 at 21:39
1 Answers
2
ScaleTransform is an elegant solution to this particular case, but there could be more generic applications (such as binding the same list but with different permutations applied).
It is possible to do this all with converters if you make sure to consider that the binding is to the list, rather than the elements of the list. Assuming that your using an ObservableCollection of strings (sure it would be possible to use generics and reflection to make this more elegant) and missing out all the proper coding of exception handling and multiple calls to Convert...
public class ReverseListConverter : MarkupExtension, IValueConverter
{
private ObservableCollection<string> _reversedList;
public override object ProvideValue(IServiceProvider serviceProvider)
{
return this;
}
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
_reversedList = new ObservableCollection<string>();
var data = (ObservableCollection<string>) value;
for (var i = data.Count - 1; i >= 0; i--)
_reversedList.Add(data[i]);
data.CollectionChanged += DataCollectionChanged;
return _reversedList;
}
void DataCollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
var data = (ObservableCollection<string>)sender;
_reversedList.Clear();
for (var i = data.Count - 1; i >= 0; i--)
_reversedList.Add(data[i]);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotSupportedException();
}
}
You can then bind within your XAML with something like
<ListBox ItemsSource="{Binding Converter={ReverseListConverter}}"/>

Iain Skett
- 991
- 4
- 8
-
ScaleTransform sounds like an hack in my opinion! Scale transormations are not intended for arrangements purpose so I thought there must be a better way to achive this. Using a converter is a very clean solution, I'll do some tests. Thank you! – Gigitsu Sep 14 '11 at 08:49
-
It really comes down to what you mean elegant means, it's a very neat and clever solution to a particular problem. I should note that the above is only for a read-only list, if you want to make it writable then you'll need to add a callback to the reversedList's DataChanged event. – Iain Skett Sep 14 '11 at 09:04
-
I've already added a callback to the reversed list's DataChanged event, seems to work well. Do you think is better the ScaleTransform? – Gigitsu Sep 14 '11 at 10:51
-
The converter is a far better solution which will cover far more cases such as editable lists, application of templates to your items, permutations on lists, etc, and will also be far more supportable code in the future. I only mention that ScaleTransform is clever from a theoretical perspective, but would never suggest its usage in any practical application. – Iain Skett Sep 14 '11 at 14:35