2017-12-07 23 views
0

사용자가 작업중인 JobType을 선택할 수있는 ComboBox가 있습니다. ComboBox에는 AllJobTypes의 목록이 있습니다. 문제는 사용자가 새 JobType을 추가 할 때부터 JobType을 AllJobTypes ObservableCollection에 추가 한 다음 정렬 할 때 발생합니다. 정렬이 발생하면 ComboBox get은 선택 취소되고 실제로 이유는 알 수 없습니다. 이 프로세스에서는 JobConfig.SelectedJobType.Name이 변경되지 않습니다. ComboBox를 손상시키지 않는 관찰 가능한 컬렉션을 정렬하는 방법이 있습니까?WPF ObservableCollection을 정렬하면 ComboBox가 선택 취소됩니다.

<Window ... 
    xmlns:scm="clr-namespace:System.ComponentModel;assembly=WindowsBase" 
    ...> 
    <Window.Resources> 
     <CollectionViewSource x:Key="cvs" Source="{Binding AllJobTypes}"> 
      <CollectionViewSource.SortDescriptions> 
       <scm:SortDescription PropertyName="Name"/> 
      </CollectionViewSource.SortDescriptions> 
     </CollectionViewSource> 
    </Window.Resources> 

    ... 
    <ComboBox ItemsSource="{Binding Source={StaticResource cvs}}" 
       DisplayMemberPath="Name" 
       SelectedValuePath="Name" 
       SelectedValue="{Binding JobConfig.SelectedJobType.Name}"/> 
    ... 

</Window> 
:
public class JobTypeList : ObservableCollection<JobType> { 

    public void SortJobTypes() { 
    var sortableList = new List<JobType>(this); 
    sortableList.Sort((x, y) => x.Name.CompareTo(y.Name)); 
    //this works but it creates a bug in the select for JobTypes 
    for (int i = 0; i < sortableList.Count; i++) { 
     this.Move(this.IndexOf(sortableList[i]), i); 
    } 
    } 

대신 뷰 모델에서 컬렉션을 정렬, 당신이 SortDescription을 지정할 수 있습니다 CollectionViewSource에 콤보 상자의 ItemsSource를 결합한다의 XAML

<ComboBox Grid.Column="0" SelectionChanged="JobTypeComboBox_SelectionChanged" 
           Name="JobTypeComboBox" 
           ItemsSource="{Binding Path=AllJobTypes}" 
           DisplayMemberPath="Name" 
           SelectedValuePath="Name" 
           SelectedValue="{Binding 
Path=JobConfig.SelectedJobType.Name}" /> 
+1

당신이 SelectedValue보다는 ItemsSource/selectedItem가 쌍으로 결합 변경해보십시오 당신의 JobTypesList 사용. SelectedValue 바인딩은 몇 가지 이유로 흡사합니다. 이것은 새로운 것이 될 수 있습니다. – Will

+0

이로 인해 동일한 문제가 발생합니다. –

+0

No repro. 넌 다른 뭔가 잘못하고있어. – Will

답변

1

다음은 ItemsSource/SelectedItem을 사용하는 버전입니다. 새 항목을 목록에 추가하고보기에서 현재 선택된 항목을 잃지 않고 정렬 할 수 있습니다.

<Window 
    x:Class="SortingAList.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:local="clr-namespace:SortingAList" 
    mc:Ignorable="d" 
    Title="MainWindow" 
    Height="350" 
    Width="525"> 
    <Grid> 
     <Grid.RowDefinitions> 
      <RowDefinition /> 
      <RowDefinition /> 
     </Grid.RowDefinitions> 
     <TextBox 
      Text="{Binding NewJobType, Delay=1000}" 
      HorizontalAlignment="Center" 
      VerticalAlignment="Center" 
      Width="200" /> 
     <ComboBox 
      Grid.Row="1" 
      ItemsSource="{Binding JobTypes}" 
      SelectedItem="{Binding SelectedJobType}" 
      DisplayMemberPath="Name" 
      HorizontalAlignment="Center" 
      VerticalAlignment="Center" 
      Width="200" /> 
    </Grid> 
</Window> 

코드

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 
     DataContext = new ViewModel(); 
    } 
} 

public class Notifier : INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 
    protected void Notify([CallerMemberName]string property = null) 
    { 
     PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property)); 
    } 
} 

public class ViewModel : Notifier 
{ 
    private JobType _selectedJobType; 
    private string _newJobType; 

    public JobTypeList JobTypes { get; private set; } 
    public JobType SelectedJobType { get => _selectedJobType; set { _selectedJobType = value; Notify(); } } 
    public string NewJobType { get => _newJobType; set { _newJobType = value; Notify(); AddNewJobType(value); } } 
    public ViewModel() 
    { 
     JobTypes = new JobTypeList(); 
     JobTypes.Add(new JobType { Name = "Butcher" }); 
     JobTypes.Add(new JobType { Name = "Baker" }); 
     JobTypes.Add(new JobType { Name = "LED maker" }); 
    } 

    private void AddNewJobType(string name) 
    { 
     if(JobTypes.Any(x => x.Name == name)) return; 
     JobTypes.Add(new JobType { Name = name }); 
     JobTypes.SortJobTypes(); 
    } 
} 
public class JobType : Notifier 
{ 
    private string _name; 

    public string Name { get => _name; set { _name = value; Notify(); } } 
} 

public class JobTypeList : ObservableCollection<JobType> 
{ 

    public void SortJobTypes() 
    { 
     var sortableList = new List<JobType>(this); 
     sortableList.Sort((x, y) => x.Name.CompareTo(y.Name)); 
     //this works but it creates a bug in the select for JobTypes 
     for(int i = 0; i < sortableList.Count; i++) 
     { 
      this.Move(this.IndexOf(sortableList[i]), i); 
     } 
    } 
} 
+0

나는 이미 대답을 받아 들였지만, 당신이 넣은 일에 대해 이것을 시도하고 +1 할 것이다. 고마워. –

+1

@SariRahal NP 정답입니다. 선택한 사람이 잘 할거야. 당신이이 방법을 사용하여 설명 한 것과 같은 문제는 없을 것이라고 생각했기 때문에 2 분 동안 재현을 시작했습니다. 다른 사람들에게 유용 할 거라고 생각했기 때문에 대답으로 추가했습니다. – Will