나는 일종의 그룹화 기능이 켜져있을 때 WPF DataGrid 정렬을 해제하는 방법?
MyCollectionViewSource.GroupDescriptions.Add(new PropertyGroupDescription("Table"));
뷰 모델
에서의 그룹화 (ItemsSource는 CollectionViewSource에 바인딩) 및 턴 데이터 그리드에서 한 열이 나는 예외를 얻을 경우 : 명령 핸들러 'GroupDataGrid'시스템에처리되지 않은 예외. InvalidOperationException : 배열의 두 요소를 비교하지 못했습니다. ---> System.ArgumentException : 적어도 하나의 개체 IComparable 구현해야합니다.
는 그러나 GroupDescription을 추가하기 전에 나는 정렬을 제거하려고 :
MyCollectionViewSource.SortDescriptions.Clear();
이 충분하지 않습니다 어떤 이유. 스택 추적 :
at System.Collections.Comparer.Compare(Object a, Object b)
at MS.Internal.Data.SortFieldComparer.Compare(Object o1, Object o2)
at System.Array.SorterGenericArray.SwapIfGreaterWithItems(Int32 a, Int32 b)
at System.Array.SorterGenericArray.PickPivotAndPartition(Int32 lo, Int32 hi)
at System.Array.SorterGenericArray.IntroSort(Int32 lo, Int32 hi, Int32 depthLimit)
at System.Array.SorterGenericArray.IntrospectiveSort(Int32 left, Int32 length)
--- End of inner exception stack trace ---
at System.Array.SorterGenericArray.IntrospectiveSort(Int32 left, Int32 length)
at System.Array.Sort(Array keys, Array items, Int32 index, Int32 length, IComparer comparer)
at System.Array.Sort(Array array, IComparer comparer)
at MS.Internal.Data.SortFieldComparer.SortHelper(ArrayList al, IComparer comparer)
at MS.Internal.Data.DataExtensionMethods.Sort(IList list, IComparer comparer)
at System.Windows.Data.ListCollectionView.PrepareLocalArray()
at System.Windows.Data.ListCollectionView.RefreshOverride()
at System.Windows.Data.CollectionView.RefreshInternal()
at System.Windows.Data.CollectionView.RefreshOrDefer()
at System.Windows.Data.ListCollectionView.SortDescriptionsChanged(Object sender, NotifyCollectionChangedEventArgs e)
at System.Collections.Specialized.NotifyCollectionChangedEventHandler.Invoke(Object sender, NotifyCollectionChangedEventArgs e)
at System.ComponentModel.SortDescriptionCollection.OnCollectionChanged(NotifyCollectionChangedAction action, Object item, Int32 index)
at System.ComponentModel.SortDescriptionCollection.InsertItem(Int32 index, SortDescription item)
at System.Collections.ObjectModel.Collection`1.Insert(Int32 index, T item)
at System.Windows.Controls.ItemCollection.SynchronizeCollections[T](NotifyCollectionChangedEventArgs e, Collection`1 origin, Collection`1 clone)
at System.Windows.Controls.ItemCollection.SortDescriptionsChanged(Object sender, NotifyCollectionChangedEventArgs e)
at System.Collections.Specialized.NotifyCollectionChangedEventHandler.Invoke(Object sender, NotifyCollectionChangedEventArgs e)
at System.ComponentModel.SortDescriptionCollection.OnCollectionChanged(NotifyCollectionChangedAction action, Object item, Int32 index)
at System.ComponentModel.SortDescriptionCollection.InsertItem(Int32 index, SortDescription item)
at System.Collections.ObjectModel.Collection`1.Insert(Int32 index, T item)
at System.Windows.Controls.DataGrid.AddGroupingSortDescriptions()
at System.Windows.Controls.DataGrid.OnItemsGroupDescriptionsChanged(Object sender, NotifyCollectionChangedEventArgs e)
at System.Collections.Specialized.NotifyCollectionChangedEventHandler.Invoke(Object sender, NotifyCollectionChangedEventArgs e)
at System.Collections.ObjectModel.ObservableCollection`1.OnCollectionChanged(NotifyCollectionChangedEventArgs e)
at System.Collections.ObjectModel.ObservableCollection`1.InsertItem(Int32 index, T item)
at System.Collections.ObjectModel.Collection`1.Insert(Int32 index, T item)
at System.Windows.Controls.ItemCollection.SynchronizeCollections[T](NotifyCollectionChangedEventArgs e, Collection`1 origin, Collection`1 clone)
at System.Windows.Controls.ItemCollection.OnInnerGroupDescriptionsChanged(Object sender, NotifyCollectionChangedEventArgs e)
at System.Windows.WeakEventManager.ListenerList`1.DeliverEvent(Object sender, EventArgs e, Type managerType)
at System.Windows.WeakEventManager.DeliverEvent(Object sender, EventArgs args)
at System.Collections.Specialized.CollectionChangedEventManager.OnCollectionChanged(Object sender, NotifyCollectionChangedEventArgs args)
at System.Collections.Specialized.NotifyCollectionChangedEventHandler.Invoke(Object sender, NotifyCollectionChangedEventArgs e)
at System.Collections.ObjectModel.ObservableCollection`1.OnCollectionChange(NotifyCollectionChangedEventArgs e)
at System.Collections.ObjectModel.ObservableCollection`1.InsertItem(Int32 index, T item)
at System.Collections.ObjectModel.Collection`1.Add(T item)
EDIT : reaquest가 추가 한 코드. BindingSource/ViewModel 클래스의 SetValue는 PropertyChanged 이벤트를 발생시킵니다. 행
클래스 :
public class SelectedNetObjectBindingSource : NetObjectBindingSource
{
public SelectedObjectsTableGroupBindingSource Table { get; set; }
public SelectedNetObjectBindingSource(NetObject netObject, SelectedObjectsTableGroupBindingSource table)
: base(netObject)
{
Table = table;
}
}
부모 클래스 : groupheader에 대한
public class NetObjectBindingSource : BindingSource
{
public NetObject Data { get; protected set; }
public NetObjectBindingSource(NetObject netObject)
{
Data = netObject;
}
}
클래스 :
public class SelectedObjectsTableGroupBindingSource : GroupHeaderBindingSource
{
public NetObjectTableId TableId { get; private set; }
public SelectedObjectsTableGroupBindingSource(NisTable nisTable, GroupHeadersInfo headersInfo)
: base(nisTable.TableId.ToString(), nisTable.Description, headersInfo)
{
TableId = nisTable.TableId;
}
}
그것의 부모 클래스 :
public class GroupHeaderBindingSource : BindingSource, IGroupHeader, IComparable
{
public string Name { get; private set; }
public string Description { get; private set; }
public int GroupedCount { get; set; }
private GroupHeadersInfo _headersInfo;
private bool _isExpanded;
public bool IsExpanded
{
get { return _isExpanded; }
set
{
if (SetValue(ref _isExpanded, value))
{
NisDllInterface.SetUserSetting(_headersInfo.GroupSection, Name, value ? "True" : "False");
_headersInfo.UpdateExpandedInfo(value);
}
}
}
public GroupHeaderBindingSource(string name, string description, GroupHeadersInfo headersInfo)
{
_headersInfo = headersInfo;
Name = name;
Description = description;
var value = UserSettings.Instance.GetSetting(headersInfo.GroupSection, Name);
if (value != null)
{
if (value.Equals("False"))
{
IsExpanded = false;
}
else
{
IsExpanded = true;
}
}
else
{
IsExpanded = true;
}
}
public int CompareTo(object obj)
{
if (obj != null && obj is GroupHeaderBindingSource)
{
var groupHeader = (GroupHeaderBindingSource) obj;
return Description.CompareTo(groupHeader.Description);
}
return 0;
}
}
,536,913,632 10
뷰 모델 :
public ICollectionView SelectedObjectItems
{
get
{
return _selectedObjectsView;
}
set
{
this.SetValue(ref _selectedObjectsView, value);
}
}
public bool AreSelectedObjectsGroupedByTable
{
get
{
return _areSelectedObjectsGroupedByTable;
}
set
{
this.SetValue(ref _areSelectedObjectsGroupedByTable, value);
if (_areSelectedObjectsGroupedByTable)
SelectedObjectItems.GroupDescriptions.Add(new PropertyGroupDescription("Table"));
else
SelectedObjectItems.GroupDescriptions.Clear();
SaveObjectsSetting(GroupedSettingName, _areSelectedObjectsGroupedByTable ? "True" : "False");
SelectedObjectsGroupHeaders.IsGrouped = value;
SelectedObjectItems.Refresh();
CallAfterSelectedObjectsRefresh(new GroupedRowsRefreshedEventArgs(
_areSelectedObjectsGroupedByTable ? GroupedGrid.Grouped : GroupedGrid.Ungrouped));
}
}
// in viewmodel constructor
SelectedObjectItems = CollectionViewSource.GetDefaultView(new List<NetObject>());
public void RefreshSelection()
{
RefreshSelectionObjects();
Selection = GetSelectedObjects();
// Selected objects
if (SelectedObjectsExpanded)
{
IsFetchObjectsAnywayVisible = false;
bool isTooManyObjects = SelectedObjectsInstance.Count > MaxSelectedObjectCount;
if (isTooManyObjects && !_fetchObjectsAnyway)
{
SelectedObjectsInfoPanelText = App.Current.Resources["MmsMsgTooManyObjectsSelectd"].ToString();
SelectedObjectItems = CollectionViewSource.GetDefaultView(new List<NetObject>());
ShowSelectedObjectsInfoPanel = true;
IsFetchObjectsAnywayVisible = true;
}
else if (SelectedObjectsInstance.Count == 0)
{
SelectedObjectsInfoPanelText = App.Current.Resources["NisStrNoObjectsSelected"].ToString();
SelectedObjectItems = CollectionViewSource.GetDefaultView(new List<NetObject>());
ShowSelectedObjectsInfoPanel = true;
}
else
{
SelectedObjectItems = CollectionViewSource.GetDefaultView(GetSelectedObjects().ToList());
if (_areSelectedObjectsGroupedByTable)
SelectedObjectItems.GroupDescriptions.Add(new PropertyGroupDescription("Table"));
else
SelectedObjectItems.GroupDescriptions.Clear();
ShowSelectedObjectsInfoPanel = false;
}
_selectedObjectsRefreshSkipped = false;
}
else
{
_selectedObjectsRefreshSkipped = true;
}
}
XAML
:public class NetObject : IComparable
{
// Your Items implementation ....
public int CompareProperty { get; set; }
public int CompareTo(object obj)
{
if(!(obj is NetObject)) throw new Exception("The Object can't been compared");
if (this.CompareProperty > ((NetObject)obj).CompareProperty) return 1;
if (this.CompareProperty < ((NetObject)obj).CompareProperty) return -1;
return 0;
}
}
CompareTo
는 각각에 집중할 수 :
<DataGrid Name="SelectedObjectsGrid"
Visibility="{Binding ShowSelectedObjectsInfoPanel, Converter={StaticResource ReverseBoolToVisibilityConverter}}"
ItemsSource="{Binding SelectedObjectItems}"
SelectionMode="Extended"
CanUserAddRows="False"
AutoGenerateColumns="False"
VirtualizingPanel.IsVirtualizing="True"
VirtualizingPanel.IsVirtualizingWhenGrouping="True"
VirtualizingPanel.VirtualizationMode="Standard"
IsReadOnly="True"
Grid.Row="0" Margin="0,0,4,0">
<DataGrid.Resources>
<ContextMenu x:Key="SelectedObjectRowContextMenu"
DataContext="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource Self}}">
<MenuItem Header="{DynamicResource XpStrKeepSelectionTableShort}" Command="{ui:CommandHandler KeepTable}" CommandParameter="{Binding}"/>
<MenuItem Header="{DynamicResource XpStrRemoveSelectionTableShort}" Command="{ui:CommandHandler RemoveTable}" CommandParameter="{Binding}"/>
<MenuItem Header="{DynamicResource XpStrList}" Command="{ui:CommandHandler ToggleSelectedObjectsGrouping}" CommandParameter="False"
Visibility="{Binding DataContext.AreSelectedObjectsGroupedByTable, Source={x:Reference SelectedObjectsGrid}, Converter={StaticResource BoolToVisibilityConverter}}" >
<MenuItem.Icon>
<Image>
<Image.Source>
<DrawingImage>
<DrawingImage.Drawing>
<GeometryDrawing Brush="Black"
Geometry="{Binding DataContext.AreSelectedObjectsGroupedByTable, Source={x:Reference SelectedObjectsGrid}, Converter={StaticResource ReverseBoolToGeometryConverter}}" />
</DrawingImage.Drawing>
</DrawingImage>
</Image.Source>
</Image>
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="{DynamicResource XpStrGroup}" Command="{ui:CommandHandler ToggleSelectedObjectsGrouping}" CommandParameter="True"
Visibility="{Binding DataContext.AreSelectedObjectsGroupedByTable, Source={x:Reference SelectedObjectsGrid}, Converter={StaticResource ReverseBoolToVisibilityConverter}}" >
<MenuItem.Icon>
<Image>
<Image.Source>
<DrawingImage>
<DrawingImage.Drawing>
<GeometryDrawing Brush="Black"
Geometry="{Binding DataContext.AreSelectedObjectsGroupedByTable, Source={x:Reference SelectedObjectsGrid}, Converter={StaticResource BoolToGeometryConverter}}" />
</DrawingImage.Drawing>
</DrawingImage>
</Image.Source>
</Image>
</MenuItem.Icon>
</MenuItem>
<Separator Visibility="{Binding DataContext.AreSelectedObjectsGroupedByTable, Source={x:Reference SelectedObjectsGrid}, Converter={StaticResource BoolToVisibilityConverter}}" />
<MenuItem Header="{DynamicResource XpStrHintTreeExpandAll}" Command="{ui:CommandHandler ExpandOrCollapseAll}" CommandParameter="True"
Visibility="{Binding DataContext.SelectedObjectsGroupHeaders.DoCollapsedGroupsExist, Source={x:Reference SelectedObjectsGrid}, Converter={StaticResource BoolToVisibilityConverter}}">
<MenuItem.Icon>
<Image Source="{Binding Converter={StaticResource nameToBitmapSource}}" DataContext="BmpTreeExpandAll"/>
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="{DynamicResource XpStrHintTreeCollapseAll}" Command="{ui:CommandHandler ExpandOrCollapseAll}" CommandParameter="False"
Visibility="{Binding DataContext.SelectedObjectsGroupHeaders.DoExpandedGroupsExist, Source={x:Reference SelectedObjectsGrid}, Converter={StaticResource BoolToVisibilityConverter}}">
<MenuItem.Icon>
<Image Source="{Binding Converter={StaticResource nameToBitmapSource}}" DataContext="BmpTreeCollapseAll"/>
</MenuItem.Icon>
</MenuItem>
</ContextMenu>
</DataGrid.Resources>
<DataGrid.RowStyle>
<Style TargetType="DataGridRow" BasedOn="{StaticResource Theme.DataGrid.Row.Style}">
<Setter Property="ContextMenu" Value="{StaticResource SelectedObjectRowContextMenu}" />
<EventSetter Event="MouseDoubleClick" Handler="SelectedObjectsRow_DoubleClick" />
</Style>
</DataGrid.RowStyle>
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<i:InvokeCommandAction Command="{ui:CommandHandler ObjectsGridSelectionChangedCommand}" CommandParameter="{Binding SelectedItems,ElementName=SelectedObjectsGrid}">
</i:InvokeCommandAction>
</i:EventTrigger>
</i:Interaction.Triggers>
<DataGrid.GroupStyle>
<!-- Style for groups at top level. -->
<GroupStyle>
<GroupStyle.ContainerStyle>
<Style TargetType="{x:Type GroupItem}">
<Setter Property="Margin" Value="0,0,0,5"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<Expander IsExpanded="{Binding Path=Name.IsExpanded}"
Tag="{Binding Path=Name}"
Background="#FF112255" BorderBrush="#FF002255"
Foreground="#FFEEEEEE" BorderThickness="1,1,1,5">
<Expander.ContextMenu>
<ContextMenu DataContext="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource Self}}">
<MenuItem Header="{DynamicResource XpStrKeepSelectionTableShort}" Command="{ui:CommandHandler KeepTable}" CommandParameter="{Binding Name}" />
<MenuItem Header="{DynamicResource XpStrRemoveSelectionTableShort}" Command="{ui:CommandHandler RemoveTable}" CommandParameter="{Binding Name}" />
<MenuItem Header="{DynamicResource XpStrList}" Command="{ui:CommandHandler ToggleSelectedObjectsGrouping}" CommandParameter="False" >
<MenuItem.Icon>
<Image>
<Image.Source>
<DrawingImage>
<DrawingImage.Drawing>
<GeometryDrawing Brush="Black" Geometry="{Binding DataContext.AreSelectedObjectsGroupedByTable,
Source={x:Reference SelectedObjectsGrid}, Converter={StaticResource ReverseBoolToGeometryConverter}}" />
</DrawingImage.Drawing>
</DrawingImage>
</Image.Source>
</Image>
</MenuItem.Icon>
</MenuItem>
<Separator Visibility="{Binding DataContext.AreSelectedObjectsGroupedByTable, Source={x:Reference SelectedObjectsGrid}, Converter={StaticResource BoolToVisibilityConverter}}" />
<MenuItem Header="{DynamicResource XpStrHintTreeExpandAll}" Command="{ui:CommandHandler ExpandOrCollapseAll}" CommandParameter="True"
Visibility="{Binding DataContext.SelectedObjectsGroupHeaders.DoCollapsedGroupsExist,
Source={x:Reference SelectedObjectsGrid}, Converter={StaticResource BoolToVisibilityConverter}}">
<MenuItem.Icon>
<Image Source="{Binding Converter={StaticResource nameToBitmapSource}}" DataContext="BmpTreeExpandAll"/>
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="{DynamicResource XpStrHintTreeCollapseAll}" Command="{ui:CommandHandler ExpandOrCollapseAll}" CommandParameter="False"
Visibility="{Binding DataContext.SelectedObjectsGroupHeaders.DoExpandedGroupsExist,
Source={x:Reference SelectedObjectsGrid}, Converter={StaticResource BoolToVisibilityConverter}}">
<MenuItem.Icon>
<Image Source="{Binding Converter={StaticResource nameToBitmapSource}}" DataContext="BmpTreeCollapseAll"/>
</MenuItem.Icon>
</MenuItem>
</ContextMenu>
</Expander.ContextMenu>
<Expander.Header>
<DockPanel>
<TextBlock FontWeight="Bold" Margin="5,0,0,0" IsHitTestVisible="False">
<Run Text="{Binding Path=Name.Description, Mode=OneWay}" />
<Run Text=" ("/>
<Run Text="{Binding Path=Name.GroupedCount, Mode=OneWay}" />
<Run Text=")"/>
</TextBlock>
</DockPanel>
</Expander.Header>
<Expander.Content>
<ItemsPresenter/>
</Expander.Content>
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GroupStyle.ContainerStyle>
</GroupStyle>
</DataGrid.GroupStyle>
<DataGrid.Columns>
<DataGridTextColumn Header="{DynamicResource XpStrLabel}" Binding="{Binding Data.Label}" />
<DataGridTextColumn Header="{DynamicResource XpStrClass}" Binding="{Binding Data.Class.Name}" />
</DataGrid.Columns>
</DataGrid>
당신이 배열의 요소에'IComparable'을 구현하려고 했습니까? 어떤 배열인지 알 수 있다고 가정합니다. 그러나 시계 창을 보면서 많은 것을 볼 수 있습니다. –
그룹화 및 정렬은보기가 아닌보기 모델에 속하므로 코드 숨김 대신 'xaml'과 함께 사용할 수 있습니다. List 및 DataTables와 함께 사용했으며 항상 효과가있었습니다. 처음부터'Binding' 포인트까지'CVS'를 만드는 방법을 보여줄 수 있습니까? – XAMlMAX
정렬 할 수있는 여러 열이 있기 때문에 IComparable을 구현하지 않았습니다. 거기에 그룹을 나타내는 행과 클래스를 나타내는 클래스가 있습니다. 나는 단지 DataGrid가 그룹화 될 때 정렬을 제거하고 싶었다. –