1

버그를 생성하려면 TopDataGrid에서 항목을 선택하십시오. 결과적으로 상품 모음은 BottomDataGrid에로드됩니다. 이 컬렉션은 지정한대로 Name 속성으로 정렬됩니다! 그런 다음 TopDataGrid에서 다른 항목을 선택하십시오. 결과적으로 ItemsSourceBottomDataGrid이 다시로드됩니다. 이제 컬렉션은 정렬되지 않습니다! 코드에서 지정한대로 컬렉션이 나타납니다. 또한 디버거로 _customerView을 검사하면 정렬 된 컬렉션이 표시됩니다.ObservableCollection을 ICollectionView로 정렬하면 올바르게 작동하지 않습니다.

은 내가 명시 적으로 ObservableCollectionICollectionView 대신 자체를 업데이트하기 위해 UI를 명령하는 OrderByINotifyPropertyChangedList을 사용할 수 있습니다 알고 있습니다. 그러나 나는 이것이 적절한 접근법이 아니라고 생각한다.

Win 7, .Net 4.0. 복사하여 붙여 넣기 만하면됩니다. ClearSortDescriptionsOnItemsSourceChange 방법의 분류에서 삭제하고 다시 재 서술되지 않은 것처럼

<Grid> 
    <Grid.RowDefinitions> 
     <RowDefinition Height="*"/> 
     <RowDefinition Height="*"/> 
     <RowDefinition Height="Auto"/> 
    </Grid.RowDefinitions> 
    <DataGrid Grid.Row="0" 
       AutoGenerateColumns="False" 
       ItemsSource="{Binding Items}" 
       SelectedItem="{Binding SelectedItem, Mode=TwoWay}" 
       CanUserAddRows="False" 
       CanUserDeleteRows="False" 
       CanUserResizeRows="False" 
       CanUserSortColumns="False" 
       SelectionMode="Single" 
       SelectionUnit="FullRow"> 
     <DataGrid.Columns> 
      <DataGridTextColumn Binding="{Binding Name}"></DataGridTextColumn> 
     </DataGrid.Columns> 
    </DataGrid> 
    <DataGrid Grid.Row="1" 
       AutoGenerateColumns="False" 
       ItemsSource="{Binding SelectedItem.MyCollectionView}" 
       CanUserAddRows="False" 
       CanUserDeleteRows="False" 
       CanUserResizeRows="False" 
       CanUserSortColumns="False" 
       SelectionMode="Single" 
       SelectionUnit="FullRow"> 
     <DataGrid.Columns> 
      <DataGridTextColumn Binding="{Binding Name}"></DataGridTextColumn> 
      <DataGridTextColumn Binding="{Binding Index}"></DataGridTextColumn> 
     </DataGrid.Columns> 

    </DataGrid> 

    <Grid Grid.Row="2"> 
     <Grid.ColumnDefinitions> 
      <ColumnDefinition/> 
      <ColumnDefinition/> 
     </Grid.ColumnDefinitions> 
     <TextBox Grid.Column="0" 
        Text="{Binding Name1}"></TextBox> 
     <TextBox Grid.Column="1" 
        Text="{Binding Index}"></TextBox> 
    </Grid> 
</Grid> 

코드

public class TopGridItem 
{ 
    private ObservableCollection<BottomGridItem> _collection; 
    public ObservableCollection<BottomGridItem> Collection 
    { 
     get { return _collection; } 
    } 

    public String Name { get; set; } 

    public ICollectionView MyCollectionView 
    { 
     get 
     { 
      ICollectionView _customerView = CollectionViewSource.GetDefaultView(Collection); 
      _customerView.SortDescriptions.Add(new SortDescription("Name", ListSortDirection.Ascending)); 

      return _customerView; 
     } 
    } 

    public TopGridItem() 
    { 
     _collection = new ObservableCollection<BottomGridItem>(); 
     _collection.Add(new BottomGridItem { Name = "bbbbbb" }); 
     _collection.Add(new BottomGridItem { Name = "aaaaa" }); 
     _collection.Add(new BottomGridItem { Name = "aaaaa" }); 
     _collection.Add(new BottomGridItem { Name = "ccccc" }); 
     _collection.Add(new BottomGridItem { Name = "dddddd" }); 
    } 

} 

public class BottomGridItem 
{ 
    public String Name { get; set; } 
    public String Index { get; set; } 
} 

/// <summary> 
/// Логика взаимодействия для NewWindow.xaml 
/// </summary> 
public partial class ProgressWindow : INotifyPropertyChanged 
{ 
    public TopGridItem _selectedItem; 

    public String Name1 { get; set; } 
    public String Index { get; set; } 
    public ObservableCollection<TopGridItem> Items { get; set; } 

    public TopGridItem SelectedItem 
    { 
     get { return _selectedItem; } 

     set 
     { 
      _selectedItem = value; 
      OnPropertyChanged("SelectedItem"); 

     } 
    } 

    public ProgressWindow() 
    { 
     InitializeComponent(); 
     DataContext = this; 

     Items = new ObservableCollection<TopGridItem>(); 
     Items.Add(new TopGridItem {Name = "One"}); 
     Items.Add(new TopGridItem {Name = "Two"}); 
     Items.Add(new TopGridItem {Name = "Three"}); 
    } 

    #region INotifyPropertyChanged 

    public event PropertyChangedEventHandler PropertyChanged; 

    [NotifyPropertyChangedInvocator] 
    protected virtual void OnPropertyChanged(string propertyName) 
    { 
     PropertyChangedEventHandler handler = PropertyChanged; 
     if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName)); 
    } 

    #endregion 
} 

UPDATE는

private void ClearSortDescriptionsOnItemsSourceChange() 
    { 
     this.Items.SortDescriptions.Clear(); 
     this._sortingStarted = false; 
     List<int> descriptionIndices = this.GroupingSortDescriptionIndices; 
     if (descriptionIndices != null) 
     descriptionIndices.Clear(); 
     foreach (DataGridColumn dataGridColumn in (Collection<DataGridColumn>) this.Columns) 
     dataGridColumn.SortDirection = new ListSortDirection?(); 
    } 

    private static object OnCoerceItemsSourceProperty(DependencyObject d, object baseValue) 
    { 
     DataGrid dataGrid = (DataGrid) d; 
     if (baseValue != dataGrid._cachedItemsSource && dataGrid._cachedItemsSource != null) 
     dataGrid.ClearSortDescriptionsOnItemsSourceChange(); 
     return baseValue; 
    } 

보인다. 나는 이것이 문제라고 생각한다. 이 INotifyPropertyChanged를 구현 있도록

다음 그래서 같은 MyCollectionView 속성을 변경하여 TopGridItem 클래스를 변경

O) :

public ICollectionView MyCollectionView 
{ 
    get 
    { 
     return _myCollectionView; 
    } 
    set 
    { 
     _myCollectionView = value; 
     OnPropertyChanged("MyCollectionView"); 
    } 
} 
ICollectionView _myCollectionView; 

지금처럼 TopGridItem에 공용 메서드를 추가합니다

+0

https://msdn.microsoft.com/en- 'TopGridItem' 생성자 ('SortDescriptions'와 함께)에서'_collection'의 /usr/library/ystem.windows.data.listcollectionview (v = vs.110) .aspx) 항상'MyCollectionView'에 반환합니다. – dkozl

+0

@ dkozl does't 작업. 모두 같음 – monstr

+0

사용자가 위쪽 모눈 항목을 클릭 할 때 _collection 목록을 정렬하거나 정렬하지 않겠습니까? – SwDevMan81

답변

1

적어도 두 솔루션.

첫째 :

public TopGridItem SelectedItem 
{ 
    get { return _selectedItem; } 

    set 
    { 
     _selectedItem = value; 
     OnPropertyChanged("SelectedItem"); 

     // _dataGrid - link to BottomDataGrid 
     _dataGrid.Items.SortDescriptions.Add(new SortDescription("Name", ListSortDirection.Ascending)); 

    } 
} 

둘째 : 당신이 _collection` 한 번만 [`ListCollectionView`]의 인스턴스를 (생성 '을 만들 수 있기 때문에

public TopGridItem SelectedItem 
{ 
    get { return _selectedItem; } 

    set 
    { 
     _selectedItem = value; 
     OnPropertyChanged("SelectedItem"); 

     if (_selectedItem != null) 
     _selectedItem.MyCollectionView.Refresh(); 
    } 
} 
0

해키 해결 방법은

public void ResetView() 
{ 
    MyCollectionView = null; // This is the key to making it work 
    ICollectionView customerView = CollectionViewSource.GetDefaultView(_collection); 
    customerView.SortDescriptions.Add(new SortDescription("Name", ListSortDirection.Ascending)); 
    MyCollectionView = customerView; 
} 

이렇게하려면 _collection을 i라는 변수가 아닌 클래스 필드로 만들어야합니다. 생성자에서만 사용됩니다. 말하기 :

public TopGridItem() 
{ 
    _collection = new ObservableCollection<BottomGridItem>(); 
    _collection.Add(new BottomGridItem { Name = "bbbbbb" }); 
    _collection.Add(new BottomGridItem { Name = "aaaaa" }); 
    _collection.Add(new BottomGridItem { Name = "aaaaa" }); 
    _collection.Add(new BottomGridItem { Name = "ccccc" }); 
    _collection.Add(new BottomGridItem { Name = "dddddd" }); 

    ResetView(); 
} 

ResetView으로 문의하십시오.

지금, 당신은 ProgressWindowSelectedItem 속성 setter에서 할 필요는 ResetView 메소드를 호출 할 때 선택 변경 :

public TopGridItem SelectedItem 
{ 
    get { return _selectedItem; } 

    set 
    { 
     _selectedItem = value; 
     OnPropertyChanged("SelectedItem"); 

     if (_selectedItem != null) 
     { 
      _selectedItem.ResetView(); 
     } 
    } 
} 

내가 여기를 테스트 한 작동하는 것 같다. 그렇지 않으면 내가 어딘가에서 오타를 만들었거나 내가 게시 한 코드에서 뭔가를 놓쳤을 것입니다.코드의


작업 버전

XAML :

<Window x:Class="WpfApplication4.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="MainWindow" 
     Height="350" 
     Width="525"> 
    <Grid> 
     <Grid.RowDefinitions> 
      <RowDefinition Height="*" /> 
      <RowDefinition Height="*" /> 
      <RowDefinition Height="Auto" /> 
     </Grid.RowDefinitions> 
     <DataGrid Grid.Row="0" 
        AutoGenerateColumns="False" 
        ItemsSource="{Binding Items}" 
        SelectedItem="{Binding SelectedItem, Mode=TwoWay}" 
        CanUserAddRows="False" 
        CanUserDeleteRows="False" 
        CanUserResizeRows="False" 
        CanUserSortColumns="False" 
        SelectionMode="Single" 
        SelectionUnit="FullRow"> 
      <DataGrid.Columns> 
       <DataGridTextColumn Binding="{Binding Name}"></DataGridTextColumn> 
      </DataGrid.Columns> 
     </DataGrid> 

     <DataGrid Grid.Row="1" 
        AutoGenerateColumns="False" 
        ItemsSource="{Binding SelectedItem.MyCollectionView}" 
        CanUserAddRows="False" 
        CanUserDeleteRows="False" 
        CanUserResizeRows="False" 
        CanUserSortColumns="False" 
        SelectionMode="Single" 
        SelectionUnit="FullRow"> 
      <DataGrid.Columns> 
       <DataGridTextColumn Binding="{Binding Name}"></DataGridTextColumn> 
       <DataGridTextColumn Binding="{Binding Index}"></DataGridTextColumn> 
      </DataGrid.Columns> 
     </DataGrid> 

     <Grid Grid.Row="2"> 
      <Grid.ColumnDefinitions> 
       <ColumnDefinition /> 
       <ColumnDefinition /> 
      </Grid.ColumnDefinitions> 
      <TextBox Grid.Column="0" 
        Text="{Binding Name1}"></TextBox> 
      <TextBox Grid.Column="1" 
        Text="{Binding Index}"></TextBox> 
     </Grid> 
    </Grid> 
</Window> 

코드 숨김 내가 제안 할 생각 몇 가지 조사와 시도 후

using System; 
using System.Collections.ObjectModel; 
using System.ComponentModel; 
using System.Windows; 
using System.Windows.Data; 

namespace WpfApplication4 
{ 
    public partial class MainWindow : Window, INotifyPropertyChanged 
    { 
     public MainWindow() 
     { 
      InitializeComponent(); 
      DataContext = this; 
      Items = new ObservableCollection<TopGridItem>(); 
      Items.Add(new TopGridItem { Name = "One" }); 
      Items.Add(new TopGridItem { Name = "Two" }); 
      Items.Add(new TopGridItem { Name = "Three" }); 
     } 

     public String Name1 { get; set; } 
     public String Index { get; set; } 
     public ObservableCollection<TopGridItem> Items { get; private set; } 

     public TopGridItem SelectedItem 
     { 
      get { return _selectedItem; } 
      set 
      { 
       _selectedItem = value; 
       OnPropertyChanged("SelectedItem"); 
       if (_selectedItem != null) 
       { 
        _selectedItem.ResetView(); 
       } 
      } 
     } 
     TopGridItem _selectedItem; 

     public event PropertyChangedEventHandler PropertyChanged; 

     protected virtual void OnPropertyChanged(string propertyName) 
     { 
      PropertyChangedEventHandler handler = PropertyChanged; 
      if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 

    public class TopGridItem : INotifyPropertyChanged 
    { 
     public event PropertyChangedEventHandler PropertyChanged; 

     protected virtual void OnPropertyChanged(string propertyName) 
     { 
      PropertyChangedEventHandler handler = PropertyChanged; 
      if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName)); 
     } 

     public String Name { get; set; } 

     public ICollectionView MyCollectionView 
     { 
      get 
      { 
       return _myCollectionView; 
      } 
      set 
      { 
       _myCollectionView = value; 
       OnPropertyChanged("MyCollectionView"); 
      } 
     } 
     ICollectionView _myCollectionView; 

     public void ResetView() 
     { 
      MyCollectionView = null; 
      ICollectionView _customerView = CollectionViewSource.GetDefaultView(_collection); 
      _customerView.SortDescriptions.Add(new SortDescription("Name", ListSortDirection.Ascending)); 
      MyCollectionView = _customerView; 
     } 

     ObservableCollection<BottomGridItem> _collection; 

     public TopGridItem() 
     { 
      _collection = new ObservableCollection<BottomGridItem>(); 
      _collection.Add(new BottomGridItem { Name = "bbbbbb" }); 
      _collection.Add(new BottomGridItem { Name = "aaaaa" }); 
      _collection.Add(new BottomGridItem { Name = "aaaaa" }); 
      _collection.Add(new BottomGridItem { Name = "ccccc" }); 
      _collection.Add(new BottomGridItem { Name = "dddddd" }); 
      ResetView(); 
     } 
    } 

    public class BottomGridItem 
    { 
     public String Name { get; set; } 
     public String Index { get; set; } 
    } 
} 
+0

저에게 맞지 않습니다. – monstr

+0

@monstr 내 작업의 맨 아래에 전체 작업 코드를 추가했습니다. 이것은 내가 작성한 테스트 애플리케이션에서 코드에 기반하여 복사 및 붙여 넣기되었습니다. 나는 그것이 나를 위해 일하는 것 같았다. 그것이 당신을 위해 작동하지 않는다면 그 밖의 무엇을 제안해야할지 모르겠다. 미안하다. –

+0

@ Steven Rands, 복사 붙여 넣기. 아직도 나를 위해 작동하지 않습니다. 컬렉션이 전혀 정렬되지 않았습니다. 나는 이미 더 나은 솔루션을 찾았습니다. thy :) – monstr