ViewModel的多个实例

时间:2016-07-29 19:33:23

标签: c# wpf xaml

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

为什么我有两个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与SetSelectedPrices方法中的SelectedPrices具有不同的内存地址。

我需要这些同步。

2 个答案:

答案 0 :(得分:4)

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

要在Code-Behind中访问它,请使用AdminViewModel抓住(AdminViewModel)this.DataContext

干杯

答案 1 :(得分:1)

删除

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

试试这个;

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