更改 ICollectionView 中的项目组
change the group of item in ICollectionView
我有 ICollectionView
看起来像
public ICollectionView UsersCollectionView
{
get
{
var view = CollectionViewSource.GetDefaultView(this);
view.GroupDescriptions.Add(new PropertyGroupDescription("SeriesName"));
view.SortDescriptions.Add(new SortDescription("CreationDate", ListSortDirection.Ascending));
view.SortDescriptions.Add(new SortDescription("DocumentTypeId", ListSortDirection.Ascending));
return view;
}
}
我想使用拖放来更改项目系列名称,以及在列表视图中的位置知道如何做到这一点,例如
--- ScienceFiction
------------> Book1
------------> Book2
--- History
------------> Book3
------------> Book4
如果 Idraged and drop book3 in ScienceFiction 输出应该是
--- ScienceFiction
------------> Book1
------------> Book2
------------> Book3
--- History
------------> Book4
我使用 xaml 这样的代码 :
<UserControl.Resources>
<Style x:Key="ContainerStyle" TargetType="{x:Type GroupItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Expander Header="{Binding Name}" IsExpanded="True">
<ItemsPresenter />
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<Grid>
<ListBox x:Name="lbPersonList" Margin="19,17,162,25" AlternationCount="2" ItemsSource="{Binding}">
<ListBox.GroupStyle>
<GroupStyle ContainerStyle="{StaticResource ContainerStyle}"/>
</ListBox.GroupStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
遗憾的是 .net 尚未提供 "easy to use" 拖放的实现。你必须自己构建一堆东西。起点是 Behavior
开始拖动,ContentControl
是用户可以放置东西的区域。定义了这些之后,您可以轻松地重用这个概念。在下面的示例中,StackPanel
可以 "dragged" 到 TextBlock
周围的不可见 "area" 上。这样你就可以实现手动排序你的书(将书放在鼠标指针下before/behind)。
如果你想把书放到你的 headers 上,用 DropArea
包围它们。您也可以采用这两种方式。
您的 xaml 将如下所示:
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
[...]
<ListBox x:Name="lbPersonList" Margin="19,17,162,25" AlternationCount="2" ItemsSource="{Binding}">
<ListBox.GroupStyle>
<GroupStyle ContainerStyle="{StaticResource ContainerStyle}"/>
</ListBox.GroupStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<myOwn:DropArea>
<TextBlock Text="{Binding Name}"/>
</myOwn:DropArea>
<i:Interaction.Behaviors>
<myOwn:DragBehavior/>
</i:Interaction.Behaviors>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
DragBehavior
看起来像:
public class DragBehavior : Behavior<FrameworkElement>
[...]
protected override void OnAttached()
{
AssociatedObject.MouseMove += AssociatedObject_MouseMove;
AssociatedObject.MouseDown += AssociatedObject_MouseLeftButtonDown;
AssociatedObject.MouseLeave += AssociatedObject_MouseLeave;
base.OnAttached();
}
protected override void OnDetaching()
{
AssociatedObject.MouseMove -= AssociatedObject_MouseMove;
AssociatedObject.MouseDown -= AssociatedObject_MouseLeftButtonDown;
AssociatedObject.MouseLeave -= AssociatedObject_MouseLeave;
base.OnDetaching();
}
protected virtual void AssociatedObject_MouseMove(object sender, MouseEventArgs e)
{
if (some condition of mouse button states or mouse moves)
{
DataObject data = new DataObject();
data.SetData(typeof(anyKeyType), anyData);
data.SetData(typeof(anyOtherKeyType), anyOtherData);
DragDrop.DoDragDrop(fe, data, DragDropEffects.Move);
}
}
DropArea
看起来像:
public class DropArea : ContentControl
[...]
public DropArea()
{
DragEnter += AssociatedObjectDragEnter;
DragLeave += AssociatedObjectDragLeave;
DragOver += AssociatedObjectDragOver;
IsTabStop = false;
AllowDrop = true;
}
protected override void AssociatedObjectDrop(object sender, DragEventArgs e)
{
object o = e.Data.GetData(typeof(anyKeyType));
//handle dropped data
}
希望对您有所帮助。可能有任何框架或库可以解决该问题,但您可以通过这种方式满足自己的需求。
AMH,
首先修改ListviewItem Style。它是包含列表框每一行(数据模板实例化)的容器。这是在行级别管理拖放的好地方(不是行的控件,DataTemplate 中可能有很多)。
在Visual Studio、select列表框,右击,编辑附加templates/Edit Generated Item Container(ItemContainerStyle)/编辑一个副本
在创建的 ListBoxItemStyle 中,将这三个声明添加到 setter 中:
<EventSetter Event="ListBoxItem.DragOver" Handler="ListBoxItemDragOver"/>
<EventSetter Event="ListBoxItem.Drop" Handler="ListBoxItemDrop"/>
<EventSetter Event="ListBoxItem.PreviewMouseMove" Handler="ListBoxItemPreviewMouseMove"/>
在 ListBox 上将 AllowDrop 属性 设置为 true :
<ListBox x:Name="listboxBooks" AllowDrop="True">
然后在 .xaml.cs 代码中实现处理程序 :
#region DnD management
private Book sourceBook;
private void ListBoxItemPreviewMouseMove(object sender, MouseEventArgs e)
{
if (e.LeftButton != MouseButtonState.Pressed)
return;
var listboxItem = sender as ListBoxItem;
if (listboxItem == null)
return;
sourceBook = listboxItem.DataContext as Book;
if (sourceBook == null)
return;
var data = new DataObject();
data.SetData(sourceBook);
// provide some data for DnD in other applications (Word, ...)
data.SetData(DataFormats.StringFormat, sourceBook.ToString());
DragDropEffects effect = DragDrop.DoDragDrop(listboxItem, data, DragDropEffects.Move | DragDropEffects.Copy);
}
private void ListBoxItemDrop(object sender, DragEventArgs e)
{
if (!e.Data.GetDataPresent(typeof(Book)))
return;
var listBoxItem = sender as ListBoxItem;
if (listBoxItem == null)
return;
var targetBook = listBoxItem.DataContext as Book;
if (targetBook != null)
{
viewModel.RecategorizeBook(sourceBook, targetBook.Category);
}
e.Handled = true;
}
private void ListBoxItemDragOver(object sender, DragEventArgs e)
{
Debug.WriteLine(e.Effects);
if (!e.Data.GetDataPresent(typeof(Book)))
{
e.Effects = DragDropEffects.None;
e.Handled = true;
}
}
private void GroupItemDrop(object sender, DragEventArgs e)
{
if (!e.Data.GetDataPresent(typeof(Book)))
return;
var groupItem = sender as GroupItem;
if (groupItem == null)
return;
dynamic targetGroup = groupItem.DataContext;
if (targetGroup != null)
{
// here I change the category of the book
// and refresh the view of the collectionViewSource ( see link to project zipped further)
viewModel.RecategorizeBook(sourceBook, targetGroup.Name as String);
}
e.Handled = true;
}
#endregion
请注意,我还在处理程序中对组 header 实施了 Drop 管理。
所以处理程序需要在 XAML groupstyle 中声明:
<ListBox.GroupStyle>
<GroupStyle>
<GroupStyle.ContainerStyle>
<Style TargetType="{x:Type GroupItem}">
<EventSetter Event="GroupItem.Drop" Handler="GroupItemDrop"/>
<EventSetter Event="GroupItem.PreviewMouseMove" Handler="ListBoxItemPreviewMouseMove"/>
有效,这是完整的工作代码:http://1drv.ms/1FhBZwr
祝你代码尽可能好
我有 ICollectionView
看起来像
public ICollectionView UsersCollectionView
{
get
{
var view = CollectionViewSource.GetDefaultView(this);
view.GroupDescriptions.Add(new PropertyGroupDescription("SeriesName"));
view.SortDescriptions.Add(new SortDescription("CreationDate", ListSortDirection.Ascending));
view.SortDescriptions.Add(new SortDescription("DocumentTypeId", ListSortDirection.Ascending));
return view;
}
}
我想使用拖放来更改项目系列名称,以及在列表视图中的位置知道如何做到这一点,例如
--- ScienceFiction
------------> Book1
------------> Book2
--- History
------------> Book3
------------> Book4
如果 Idraged and drop book3 in ScienceFiction 输出应该是
--- ScienceFiction
------------> Book1
------------> Book2
------------> Book3
--- History
------------> Book4
我使用 xaml 这样的代码 :
<UserControl.Resources>
<Style x:Key="ContainerStyle" TargetType="{x:Type GroupItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Expander Header="{Binding Name}" IsExpanded="True">
<ItemsPresenter />
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<Grid>
<ListBox x:Name="lbPersonList" Margin="19,17,162,25" AlternationCount="2" ItemsSource="{Binding}">
<ListBox.GroupStyle>
<GroupStyle ContainerStyle="{StaticResource ContainerStyle}"/>
</ListBox.GroupStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
遗憾的是 .net 尚未提供 "easy to use" 拖放的实现。你必须自己构建一堆东西。起点是 Behavior
开始拖动,ContentControl
是用户可以放置东西的区域。定义了这些之后,您可以轻松地重用这个概念。在下面的示例中,StackPanel
可以 "dragged" 到 TextBlock
周围的不可见 "area" 上。这样你就可以实现手动排序你的书(将书放在鼠标指针下before/behind)。
如果你想把书放到你的 headers 上,用 DropArea
包围它们。您也可以采用这两种方式。
您的 xaml 将如下所示:
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
[...]
<ListBox x:Name="lbPersonList" Margin="19,17,162,25" AlternationCount="2" ItemsSource="{Binding}">
<ListBox.GroupStyle>
<GroupStyle ContainerStyle="{StaticResource ContainerStyle}"/>
</ListBox.GroupStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<myOwn:DropArea>
<TextBlock Text="{Binding Name}"/>
</myOwn:DropArea>
<i:Interaction.Behaviors>
<myOwn:DragBehavior/>
</i:Interaction.Behaviors>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
DragBehavior
看起来像:
public class DragBehavior : Behavior<FrameworkElement>
[...]
protected override void OnAttached()
{
AssociatedObject.MouseMove += AssociatedObject_MouseMove;
AssociatedObject.MouseDown += AssociatedObject_MouseLeftButtonDown;
AssociatedObject.MouseLeave += AssociatedObject_MouseLeave;
base.OnAttached();
}
protected override void OnDetaching()
{
AssociatedObject.MouseMove -= AssociatedObject_MouseMove;
AssociatedObject.MouseDown -= AssociatedObject_MouseLeftButtonDown;
AssociatedObject.MouseLeave -= AssociatedObject_MouseLeave;
base.OnDetaching();
}
protected virtual void AssociatedObject_MouseMove(object sender, MouseEventArgs e)
{
if (some condition of mouse button states or mouse moves)
{
DataObject data = new DataObject();
data.SetData(typeof(anyKeyType), anyData);
data.SetData(typeof(anyOtherKeyType), anyOtherData);
DragDrop.DoDragDrop(fe, data, DragDropEffects.Move);
}
}
DropArea
看起来像:
public class DropArea : ContentControl
[...]
public DropArea()
{
DragEnter += AssociatedObjectDragEnter;
DragLeave += AssociatedObjectDragLeave;
DragOver += AssociatedObjectDragOver;
IsTabStop = false;
AllowDrop = true;
}
protected override void AssociatedObjectDrop(object sender, DragEventArgs e)
{
object o = e.Data.GetData(typeof(anyKeyType));
//handle dropped data
}
希望对您有所帮助。可能有任何框架或库可以解决该问题,但您可以通过这种方式满足自己的需求。
AMH,
首先修改ListviewItem Style。它是包含列表框每一行(数据模板实例化)的容器。这是在行级别管理拖放的好地方(不是行的控件,DataTemplate 中可能有很多)。 在Visual Studio、select列表框,右击,编辑附加templates/Edit Generated Item Container(ItemContainerStyle)/编辑一个副本
在创建的 ListBoxItemStyle 中,将这三个声明添加到 setter 中:
<EventSetter Event="ListBoxItem.DragOver" Handler="ListBoxItemDragOver"/>
<EventSetter Event="ListBoxItem.Drop" Handler="ListBoxItemDrop"/>
<EventSetter Event="ListBoxItem.PreviewMouseMove" Handler="ListBoxItemPreviewMouseMove"/>
在 ListBox 上将 AllowDrop 属性 设置为 true :
<ListBox x:Name="listboxBooks" AllowDrop="True">
然后在 .xaml.cs 代码中实现处理程序 :
#region DnD management
private Book sourceBook;
private void ListBoxItemPreviewMouseMove(object sender, MouseEventArgs e)
{
if (e.LeftButton != MouseButtonState.Pressed)
return;
var listboxItem = sender as ListBoxItem;
if (listboxItem == null)
return;
sourceBook = listboxItem.DataContext as Book;
if (sourceBook == null)
return;
var data = new DataObject();
data.SetData(sourceBook);
// provide some data for DnD in other applications (Word, ...)
data.SetData(DataFormats.StringFormat, sourceBook.ToString());
DragDropEffects effect = DragDrop.DoDragDrop(listboxItem, data, DragDropEffects.Move | DragDropEffects.Copy);
}
private void ListBoxItemDrop(object sender, DragEventArgs e)
{
if (!e.Data.GetDataPresent(typeof(Book)))
return;
var listBoxItem = sender as ListBoxItem;
if (listBoxItem == null)
return;
var targetBook = listBoxItem.DataContext as Book;
if (targetBook != null)
{
viewModel.RecategorizeBook(sourceBook, targetBook.Category);
}
e.Handled = true;
}
private void ListBoxItemDragOver(object sender, DragEventArgs e)
{
Debug.WriteLine(e.Effects);
if (!e.Data.GetDataPresent(typeof(Book)))
{
e.Effects = DragDropEffects.None;
e.Handled = true;
}
}
private void GroupItemDrop(object sender, DragEventArgs e)
{
if (!e.Data.GetDataPresent(typeof(Book)))
return;
var groupItem = sender as GroupItem;
if (groupItem == null)
return;
dynamic targetGroup = groupItem.DataContext;
if (targetGroup != null)
{
// here I change the category of the book
// and refresh the view of the collectionViewSource ( see link to project zipped further)
viewModel.RecategorizeBook(sourceBook, targetGroup.Name as String);
}
e.Handled = true;
}
#endregion
请注意,我还在处理程序中对组 header 实施了 Drop 管理。 所以处理程序需要在 XAML groupstyle 中声明:
<ListBox.GroupStyle>
<GroupStyle>
<GroupStyle.ContainerStyle>
<Style TargetType="{x:Type GroupItem}">
<EventSetter Event="GroupItem.Drop" Handler="GroupItemDrop"/>
<EventSetter Event="GroupItem.PreviewMouseMove" Handler="ListBoxItemPreviewMouseMove"/>
有效,这是完整的工作代码:http://1drv.ms/1FhBZwr
祝你代码尽可能好