2017-12-07 7 views
0

Ich habe eine ComboBox, in der ein Benutzer auswählen kann, an welchem ​​JobType er arbeitet. Die ComboBox hat eine Liste von AllJobTypes. Das Problem rührt daher, wenn ein Benutzer einen neuen JobType hinzufügt, ich den JobType der AllJobTypes ObservableCollection hinzufüge und sie dann sortiere. Wenn die Sortierung erfolgt, wird die ComboBox deaktiviert und nicht wirklich sicher warum. Der JobConfig.SelectedJobType.Name ändert sich in diesem Prozess nie. Gibt es eine Möglichkeit, eine beobachtbare Sammlung so zu sortieren, dass sie die ComboBox nicht unterbricht?WPF Beim Sortieren einer ObservableCollection wird eine ComboBox abgewählt

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); 
    } 
    } 

Und in der 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

Versuchen Sie, Ihre Bindung an ein Itemssource/SelectedItem Paar statt SelectedValue ändern. SelectedValue-Bindungen sind aus verschiedenen Gründen ziemlich schlecht, und das könnte ein neuer sein. – Will

+0

Dies verursacht das gleiche Problem. –

+0

Keine Repro. Du machst etwas anderes falsch. – Will

Antwort

2

Statt die Sammlung in der View-Modell sortiert wird, sollten Sie die ComboBox Itemssource an einen CollectionViewSource binden, in dem Sie eine SortDescription angeben:

<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> 

Für weitere Informationen siehe How to: Sort and Group Data Using a View in XAML

1

Hier ist eine Version mit ItemsSource/SelectedItem. Beachten Sie, dass Sie der Liste ein neues Element hinzufügen und es sortieren können, ohne das aktuell ausgewählte Element in der Ansicht zu verlieren.

Das Fenster

<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> 

Der Code

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(); } } 
} 

mit Ihrem JobTypesList

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

Ich habe bereits eine Antwort akzeptiert, aber ich werde dies versuchen und +1 für die Arbeit, die Sie eingeben. Danke. –

+1

@SariRahal NP über die richtige Antwort. Der von dir gewählte wird dir auch gut tun. Ich dachte nicht, dass es ein Problem geben würde, wie du es beschrieben hast, also brauchte ich zwei Minuten, um eine Repro zu machen. Ich habe es als Antwort hinzugefügt, da ich dachte, es könnte für andere nützlich sein. – Will

Verwandte Themen