问题
I have created a listview control in WPF and has success fully bound Icollectionview
object of ObservableCollection<object>
. My listview columns are created dynamically.
I have to sort and group my listview and it is not working properly.
My code is as below.
private void LaodList()
{
dt = new DataTable();
dt.Columns.Add("AA", typeof(string));
dt.Columns.Add("BB", typeof(string));
dt.Columns.Add("cc", typeof(string));
dt.Rows.Add("12", "66",11);
dt.Rows.Add("33", "44",22);
dt.AcceptChanges();
GridView gv = new GridView();
//gv.AllowsColumnReorder = true;
List<string> myItemsCollection = new List<string>();
for (int i = 0; i < dt.Columns.Count; i++)
{
GridViewColumn col = new GridViewColumn();
col.Header = dt.Columns[i].ColumnName;
col.DisplayMemberBinding = new Binding(string.Format("[{0}]", i));
gv.Columns.Add(col);
myItemsCollection.Add(col.Header.ToString());
}
LvItems.View = gv;
this.Source = CollectionViewSource.GetDefaultView(LoadItems(dt)) ;
LvItems.DataContext = this.Source;
cmbGroups.ItemsSource = myItemsCollection;
}
public ObservableCollection<object> LoadItems(DataTable dt)
{
ObservableCollection<object> items = new ObservableCollection<object>();
foreach (DataRow dataRow in dt.Rows)
{
items.Add(dataRow.ItemArray);
}
return items;
}
//sort////////////////////////
private void ListView_Click(object sender, RoutedEventArgs e)
{
GridViewColumnHeader currentHeader = e.OriginalSource as GridViewColumnHeader;
if (currentHeader != null && currentHeader.Role != GridViewColumnHeaderRole.Padding)
{
if (this.Source.SortDescriptions.Count((item) => item.PropertyName.Equals(currentHeader.Column.Header.ToString())) > 0)
{
SortDescription currentPropertySort = this.Source
.SortDescriptions
.First<SortDescription>(item => item.PropertyName.Equals(currentHeader.Column.Header.ToString()));
//Toggle sort direction.
ListSortDirection direction =
(currentPropertySort.Direction == ListSortDirection.Ascending) ?
ListSortDirection.Descending : ListSortDirection.Ascending;
//Remove existing sort
this.Source.SortDescriptions.Remove(currentPropertySort);
this.Source.SortDescriptions.Insert(0, new SortDescription(currentHeader.Column.Header.ToString(), direction));
}
else
{
this.Source.SortDescriptions.Insert(0, new SortDescription(currentHeader.Column.Header.ToString(), ListSortDirection.Ascending));
}
this.Source.Refresh();
}
}
//group////////////////////
private void btnGroup_Click(object sender, RoutedEventArgs e)
{
this.Source.GroupDescriptions.Clear();
PropertyInfo pinfo = typeof(object).GetProperty(cmbGroups.Text);
if (pinfo != null)
this.Source.GroupDescriptions.Add(new PropertyGroupDescription(pinfo.Name));
}
WPF code is as below
<ListView ItemsSource="{Binding}" x:Name="LvItems" ButtonBase.Click="ListView_Click" IsSynchronizedWithCurrentItem="True" Grid.Row="1" Margin="0,22,0,43">
<ListView.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<TextBlock FontSize="15" FontWeight="Bold" Text="{Binding}"/>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</ListView.GroupStyle>
</ListView>
回答1:
Since you are using WPF you shall use DataBindings. Expose your ICollectionView as a property and bind on it
public ICollectionView MyList
{
get
{
if(_mylist == null)
_mylist = CollectionViewSource.GetDefaultView(observableCollection);
return _mylist;
}
}
In the XAML you apply the binding as follows
<ListView ItemsSource="{Binding Path=MyList}"/>
And now you apply the sorting on that property
MyList.SortDescriptions.Remove(...);
MyList.SortDescriptions.Add(...);
MyList.GroupDescription.Add(...);
This has the drawback that every Remove
or Add
on a SortDescription or GroupDescription will refresh the ListView. Normally this is unwanted if you want to apply many sortings in one step. Then you should enclose the block with following:
using(MyList.DeferRefresh())
{
//put your changes in sorting and grouping here
}
来源:https://stackoverflow.com/questions/19946402/sort-and-group-icollectionview-in-wpf