Reputation: 13557
For a WPF project in need to save the width and the column order of a ListView because these are things the user can change. I guess it is no problem getting the current width but the current position seems to be a bit difficult.
In WinForms there was something like index and displayIndex but I don't see it in WPF. How is it done?
BTW : Serializing the whole control is not an option.
Edit:
I found some samples using the listView.columns property. But I don't have such a property in my listView
My XAML code is like this:
<ListView>
<ListView.View>
<GridView>
<GridViewColumn>
....
Upvotes: 5
Views: 4333
Reputation: 556
The Columns are always in the same oder that the gridView.Columns Collection is. You can hook into the gridView.CollectionChanged event to react to changes, see also WPF Listview : Column reorder event?
I am using a Behavior
to do this. There is a dependency property on the Behavior that is bound to my DataContext. You need a reference to System.Windows.Interactivity
to use interactivity.
On my DataContext there is an ObservableCollection of ColumnInfo that I store in my configuration on application exit:
public class ColumnInfo
{
public string HeaderName { get; set; }
public int Width { get; set; }
public int Index { get; set; }
}
In your control add the namespace
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
And the ListView is something like
<ListView ItemsSource="{Binding SomeCollection}">
<ListView.View>
<GridView>
<i:Interaction.Behaviors>
<b:GridViewColumnBehavior Columns="{Binding Columns}" />
</i:Interaction.Behaviors>
</GridView>
</ListView.View>
</ListView>
The Behavior I'm using (parts of it)
public class GridViewColumnBehavior : Behavior<GridView>
{
public ObservableCollection<ColumnInfo> Columns
{
get { return (ObservableCollection<ColumnInfo>)GetValue(ColumnsProperty); }
set { SetValue(ColumnsProperty, value); }
}
public static readonly DependencyProperty ColumnsProperty =
DependencyProperty.Register("Columns", typeof(ObservableCollection<ColumnInfo>), typeof(GridViewColumnBehavior), new PropertyMetadata(null, new PropertyChangedCallback(Columns_Changed)));
private static void Columns_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var b = d as GridViewColumnBehavior;
if (b == null) return;
b.SetupColumns(e.NewValue as ObservableCollection<Column>);
}
public void SetupColumns(ObservableCollection<Column> oldColumns)
{
if(oldColumns != null)
{
oldColumns.CollectionChanged -= Columns_CollectionChanged;
}
if ((Columns?.Count ?? 0) == 0) return;
AssociatedObject.Columns.Clear();
foreach (var column in Columns.OrderBy(c => c.Index))
{
AddColumn(column);
}
Columns.CollectionChanged += Columns_CollectionChanged;
}
private void Columns_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
var lookup = AssociatedObject.Columns.Select((c, i) => new { Index = i, Element = c.Header.ToString() }).ToLookup(ci => ci.Element, ci => ci.Index);
foreach (var c in Columns)
{
// store the index in the Model (ColumnInfo)
c.Index = lookup[c.HeaderName].FirstOrDefault();
}
}
}
Enjoy!
Upvotes: 1
Reputation: 497
I managed to do that using the Move(…) method of the GridView's Columns collection
If you have the new order stored somehow, you could try:
((GridView)myListView.View).Columns.Move(originalIndex, newIndex);
Edit: This is NOT XAML, but code you should put in the .xaml.cs file
Upvotes: 5