ViewModel的多个实例

本文关键字:实例 ViewModel | 更新日期: 2023-09-27 17:59:18

我有一个通过ICommand执行任务的视图。该视图对列表视图中选定项目的列表执行任务。我通过代码后面的selection_ched事件获得所选项目的列表。对这些项目的操作是通过命令执行的。视图模型中所选项目的列表在两个调用之间不匹配。选定项目后的选定项目列表是正确的,命令引用的选定项目的列表是空的。通过检查列表的内存地址,我确定该列表没有被重新实例化或清除。内存地址不同。

为什么我有两个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">
...

查看后面的代码

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属性中的SelectedPrices与SetSelectdPrices方法中的SelectedPrices具有不同的内存地址。

我需要这些同步。

ViewModel的多个实例

若要解决问题,请从XAML或代码隐藏中删除AdminViewModel

要在Code Behind中访问它,请使用(AdminViewModel)this.DataContext获取您的AdminViewModel

干杯

删除

<Window.Resources>
    <viewModels:AdminViewModel x:Key="ViewModel" />
</Window.Resources>
<Window.DataContext>
    <viewModels:AdminViewModel/>
</Window.DataContext>

试试这个;

public ExportAdminView()
{
   this.DataContext = new AdminViewModel();
   InitializeComponent();  
}