2016-07-29 4 views
0

У меня есть одно представление, которое выполняет задачи через ICommand. Представление выполняет задачу по списку выбранных элементов из списка. Я получаю список выбранного элемента через событие selection_changed в коде позади. Действие по этим элементам выполняется с помощью команды. Список выбранных элементов в модели просмотра не совпадает между двумя вызовами. Выбран список выбранных элементов после выбора элементов, список выбранных элементов, на которые ссылается команда, пуст. Я решил, что список не восстанавливается и не очищается, проверяя адреса памяти списков. Адреса памяти разные.Несколько экземпляров ViewModel

Почему у меня есть два экземпляра SelectedPrices?

Просмотр XAML

... 
<Window.Resources> 
    <viewModels:AdminViewModel x:Key="ViewModel" /> 
</Window.Resources> 
<Window.DataContext> 
    <viewModels:AdminViewModel/> 
</Window.DataContext> 
<ListView x:Name="lvCustomerPrices" 
    HorizontalAlignment="Left" 
    Margin="14,82,0,32" 
    Width="1362" 
    ItemsSource="{Binding Prices}" 
    Grid.ColumnSpan="3" 
    SelectionChanged="lvCustomerPrices_SelectionChanged"> 
... 

View Code Behind

public partial class ExportAdminView : Window 
{ 
    protected AdminViewModel ViewModel 
    { 
     get { return (AdminViewModel)Resources["ViewModel"]; } 
    } 

    public ExportAdminView() 
    { 
     InitializeComponent(); 
    } 

    private void lvCustomerPrices_SelectionChanged(object sender, SelectionChangedEventArgs e) 
    { 
     ViewModel.SetSelectedPrices(lvCustomerPrices.SelectedItems.Cast<DailyCustomerPrice>()); 
    } 
} 

Просмотр модели

public class AdminViewModel : INotifyPropertyChanged 
{ 
    public List<DailyCustomerPrice> SelectedPrices { get; set; } = new List<DailyCustomerPrice>(); 

    public bool CanExportToEmail => (SelectedPrices.Count > 0 && !string.IsNullOrEmpty(ExportEmailAddress)); 

    public ICommand ExportPricesToEmailCommand { get; set; } 

    public AdminViewModel() 
    { 
     ExportPricesToEmailCommand = new RelayCommand(ExportPrices,() => CanExportToEmail); 
     PriceEffectiveDate = DateTime.Now.Date.AddDays(1); 
    } 

    public void SetSelectedPrices(IEnumerable<DailyCustomerPrice> selectedItems) 
    { 
     SelectedPrices.Clear(); 
     SelectedPrices.AddRange(selectedItems); 
    } 
} 

RelayCommand (мне нужно очистить это и сделать отдельный класс для параметров)

public class RelayCommand : ICommand 
{ 
    private Action<object> _executeWithParameter; 
    private Action _execute; 
    private Func<bool> _canExecute; 
    private event EventHandler CanExecuteChangedInternal; 

    public RelayCommand(Action<object> execute) 
     : this(execute, DefaultCanExecute) 
    {} 

    public RelayCommand(Action execute) : this(execute, DefaultCanExecute) 
    {} 

    public RelayCommand(Action execute, Func<bool> canExecute) 
    { 
     if (execute == null) 
      throw new ArgumentNullException(nameof(execute)); 

     if (canExecute == null) 
      throw new ArgumentNullException(nameof(canExecute)); 

     this._execute = execute; 
     this._canExecute = canExecute; 
    } 


    public RelayCommand(Action<object> execute, Func<bool> canExecute) 
    { 
     if (execute == null) 
     { 
      throw new ArgumentNullException(nameof(execute)); 
     } 

     if (canExecute == null) 
     { 
      throw new ArgumentNullException(nameof(canExecute)); 
     } 

     this._executeWithParameter = execute; 
     this._canExecute = canExecute; 
    } 

    public event EventHandler CanExecuteChanged 
    { 
     add 
     { 
      CommandManager.RequerySuggested += value; 
      this.CanExecuteChangedInternal += value; 
     } 

     remove 
     { 
      CommandManager.RequerySuggested -= value; 
      this.CanExecuteChangedInternal -= value; 
     } 
    } 

    public bool CanExecute() 
    { 
     return _canExecute(); 
    } 

    public bool CanExecute(object parameter) 
    { 
     return CanExecute(); 
    } 

    public void Execute(object parameter) 
    { 
     Execute(); 
    } 

    bool ICommand.CanExecute(object parameter) 
    { 
     return CanExecute(); 
    } 

    void ICommand.Execute(object parameter) 
    { 
     Execute(); 
    } 

    public void Execute() 
    { 
     _execute(); 
    } 

    public void OnCanExecuteChanged() 
    { 
     EventHandler handler = this.CanExecuteChangedInternal; 
     //DispatcherHelper.BeginInvokeOnUIThread(() => handler.Invoke(this, EventArgs.Empty)); 
     handler?.Invoke(this, EventArgs.Empty); 
    } 

    public void Destroy() 
    { 
     _canExecute =() => false; 
     _executeWithParameter = _ => { return; }; 
     _execute = null; 
    } 

    private static bool DefaultCanExecute() 
    { 
     return true; 
    } 
} 

Выбранныеценки в свойстве AdminViewModel.CanExportToEmail имеют другой адрес памяти, чем выбранныецены в методе SetSelectedPrices.

Мне нужно, чтобы они были в синхронизации.

+0

При добавлении элемента в него, не добавлено ли другому? –

+0

Да. Элементы, добавленные в событие SelectionChanged, не существуют в свойстве CanExportToEmail, но элементы, добавленные в событие selectionChanged, сохраняются в его копии списка, когда событие снова срабатывает. Кроме того, я могу добавить элемент в коллекцию SelectedPrices в свойстве CanExportToEmail через отладчик, и они также сохраняются между вызовами. – TonyStewart871

+0

Я думаю, есть шанс, что у вас есть два экземпляра 'AdminViewModel'; если это так, то значение «этого» в этих двух местах должно также отличаться. –

ответ

3

Чтобы устранить проблему, удалите AdminViewModel из XAML или с кода-позади.

Чтобы получить к нему доступ в Code-Behind, возьмите AdminViewModel с (AdminViewModel)this.DataContext.

Cheers

Смежные вопросы