2016-11-25 2 views
1

Je souhaite supprimer un élément d'une collection ObservableCollection en adhérant à MVVM. Je comprends la tâche, je pense que je comprends assez bien la logique et l'ai implémentée, mais l'item n'est jamais supprimé dans la vue.Suppression de l'élément selectedItem de ObservableCollection à l'aide de MVVM

J'ai tracé l'application avec des points d'arrêt et la valeur de selectedProject est lue correctement. J'ai également ajouté des variables pour vérifier la taille de la collection avant et après l'instruction remove, qui étaient la même valeur afin qu'il ne supprime donc pas l'élément. Ma question est pourquoi? Qu'ai-je manqué? À quelles règles n'ai-je pas adhéré? Assez nouveau pour .NET.

** J'utilise un service WCF pour renvoyer une collection Observable de projets de ma base de données CodeFirst DB et cela est appelé dès qu'un utilisateur ouvre la vue Projets.

Voir

<ListBox ItemsSource="{Binding ProjectList, UpdateSourceTrigger=PropertyChanged}" SelectedItem="{Binding SelectedProject}" SelectedIndex="{Binding ProjectIndex}" BorderThickness="0" Margin="60,195,218.8,212.4"> 
     <ListBox.ItemTemplate> 
      <DataTemplate> 
       <TextBlock Text="{Binding ProjectName}"/> 
      </DataTemplate> 
     </ListBox.ItemTemplate> 
    </ListBox> 
    <Button Command="{Binding DeleteCommand}" Content="Up" HorizontalAlignment="Left" Margin="563,195,0,0" VerticalAlignment="Top" Height="35" Width="75"/> 

ViewModel

private ObservableCollection<Project> _projectList; 
public ObservableCollection<Project> ProjectList 
    { 
     get 
     { 
      var q = client.ReturnProjects().ToList(); 
      _projectList = new ObservableCollection<Project>(q.ToList()); 
      return _projectList; 
     } 
     set 
     { 
      _projectList = value; 
      OnPropertyChanged("ProjectList"); 
     } 

public int SelectedProject 
    { 
     get { return _selectedProject; } 
     set 
     { 
      _selectedProject = value; 
      OnPropertyChanged("SelectedProject"); 
     } 
    } 

La méthode exécutée par la commande est la suivante, la commande est frappé et la méthode appelée.

public void DeleteProject() 
     { 

      if (SelectedProject != null) 
      { 
       ProjectList.Remove(SelectedProject); 
      } 
     } 

Répondre

0

Vous avez besoin d'une liaison bidirectionnelle pour la propriété SelectedItem.

Voir

<ListBox ItemsSource="{Binding ProjectList}" 
      SelectedItem="{Binding SelectedProject, Mode=TwoWay}"> 
     <ListBox.ItemTemplate> 
      <DataTemplate> 
       <TextBlock Text="{Binding Name}" /> 
      </DataTemplate> 
     </ListBox.ItemTemplate> 
    </ListBox> 
    <Button Command="{Binding DeleteCommand}" 
      Content="Delete" 
      HorizontalAlignment="Right" 
      VerticalAlignment="Bottom" /> 

ViewModel, le modèle et la mise en œuvre ICommand

public class ViewModel : INotifyPropertyChanged 
{ 
    public ViewModel() 
    { 
     var q = new[] { new Project() { Name = "A" }, new Project() { Name = "B" }, new Project() { Name = "C" } }; 
     ProjectList = new ObservableCollection<Project>(q); 
    } 

    private ObservableCollection<Project> _projectList; 

    public ObservableCollection<Project> ProjectList 
    { 
     get 
     { 
      return _projectList; 
     } 
     set 
     { 
      _projectList = value; 
      OnPropertyChanged("ProjectList"); 
     } 
    } 

    Project _selectedProject; 
    public Project SelectedProject 
    { 
     get { return _selectedProject; } 
     set 
     { 
      _selectedProject = value; 
      OnPropertyChanged("SelectedProject"); 
     } 
    } 

    public ICommand DeleteCommand => new SimpleCommand(DeleteProject); 

    private void DeleteProject() 
    { 

     if (SelectedProject != null) 
     { 
      ProjectList.Remove(SelectedProject); 
     } 
    } 
    public event PropertyChangedEventHandler PropertyChanged; 
    private void OnPropertyChanged(string propertyName) 
    { 
     PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 
    } 
} 

public class Project 
{ 
    public string Name { get; set; } 
} 

public class SimpleCommand : ICommand 
{ 
    Action _execute; 
    public SimpleCommand(Action execute) 
    { 
     this._execute = execute; 
    } 

    public event EventHandler CanExecuteChanged; 

    public bool CanExecute(object parameter) => true; 

    public void Execute(object parameter) 
    { 
     _execute(); 
    } 
} 
+0

J'ai ajouté 'Mode = TwoWay', cela n'a pas résolu le problème. Je ne comprends pas non plus pourquoi il devrait avoir comme SelectedItem me permet seulement de récupérer l'article que je cherche à enlever. –

+0

L'utilisateur modifie la sélection dans l'interface utilisateur (View). Avec Two-Way-Binding, la propriété ViewModels SelectedItem est mise à jour. Je vais modifier ma réponse et publier une solution de travail. –

+0

Cela a du sens Thomas, merci. Ce que je ne comprends pas, c'est que lorsque je trace avec des points d'arrêt, je peux voir que l'élément selectedItem correct a été passé dans le ViewModel, cependant l'appel à supprimer ne change pas la liste dans la vue de toute façon. –

0

Je pense OnPropertyChanged (« Projectlist ») doit être appelée après la suppression de l'élément à soulever la notification pour la mise à jour de la vue.

+0

Malheureusement pas le correctif. –