MVVMLight Event to Command с моделью в качестве параметра команды - PullRequest
0 голосов
/ 07 ноября 2018

Я пытался использовать функцию MVVMLight Event to Command, чтобы связать команды в моей ViewModel с событиями, такими как TextChanged в TextBox, например. Дело в том, что в UWP Event to Command автоматически предполагает, что параметр команды является аргументами события TextChanged. Я не хочу этого, я хочу отправить модель в качестве параметра команды, например:

<ListView ItemsSource="{Binding ListaAgendaReceita}" Background="DimGray" SelectionMode="None">
    <ListView.ItemTemplate>
        <DataTemplate>
            <TextBox Text="{Binding Valor, Mode=TwoWay, Converter={StaticResource CVTStringTODecimal}, UpdateSourceTrigger=PropertyChanged}" Background="LightGray">
                <interact:Interaction.Behaviors>
                    <core:EventTriggerBehavior EventName="TextChanged">
                        <core:InvokeCommandAction Command="{Binding ElementName=usr_Receita, Path=DataContext.ModificacaoAgendaReceita}" 
                                                  CommandParameter="{Binding}"/>
                    </core:EventTriggerBehavior>
                </interact:Interaction.Behaviors>
            </TextBox>
        </DataTemplate>
    </ListView.ItemTemplate>
<ListView/>

РЕДАКТИРОВАТЬ .: этот TextBox является частью DataTemplate внутри ListView. Я отредактировал блок кода, чтобы отразить это более четко. Я также привожу тот же пример, но для CalendarDatePicker, которому всегда не удается отправить модель в качестве параметра команды, вместо этого отправив аргументы событий.

<ListView ItemsSource="{Binding ListaAgendaReceita}" Background="DimGray" SelectionMode="None">
    <ListView.ItemTemplate>
        <DataTemplate>
            <CalendarDatePicker BorderThickness="0,3,0,1" DateFormat="{}{day.integer}/{month.integer}/{year.full}"
                                Date="{Binding Data, Mode=TwoWay, Converter={StaticResource CVTDateTimeTODateTimeOffsetTwoWay}}"
                                BorderBrush="Green" Background="DarkGray">
                <interact:Interaction.Behaviors>
                    <core:EventTriggerBehavior EventName="DateChanged">
                        <core:InvokeCommandAction Command="{Binding ElementName=usr_Receita, Path=DataContext.ModificacaoAgendaReceita}"
                                                  CommandParameter="{Binding}"/>
                    </core:EventTriggerBehavior>
                </interact:Interaction.Behaviors>
            </CalendarDatePicker>
        </DataTemplate>
    </ListView.ItemTemplate>
<ListView/>

CVTDateTimeTODateTimeOffsetTwoWay - это простой конвертер, который обрабатывает свойство DateProperty, конвертируя из DateTime в DateTimeOffset и наоборот.

public class CVTDateTimeTODateTimeOffsetTwoWay : IValueConverter
{

    public object Convert(object value, Type TargetType, object parameter, string culture)
    {
        var Data = (DateTime)value;
        DateTime date = new DateTime(Data.Year, Data.Month, Data.Day, Data.Hour, Data.Minute, 0);

        return new DateTimeOffset(date);
    }

    public object ConvertBack(object value, Type TargetType, object parameter, string culture)
    {
        if (value != null)
        {
            DateTimeOffset dto = (DateTimeOffset)value;
            return new DateTime(dto.DateTime.Year, dto.DateTime.Month, dto.DateTime.Day, dto.DateTime.Hour, dto.DateTime.Minute, 0);
        }
        else return new DateTime(DateTime.Today.Year, DateTime.Today.Month, DateTime.Today.Day, 0, 0, 0);
    }

}

Поскольку TextBox находится внутри ListView, CommandParameter="{Binding}" должен быть ModelAgendaReceita, то есть моделью, которая передает ListSource ItemsView. Событие для команды продолжает передавать TextChangedEventArgs как CommandParameter, и я хочу модель.

РЕДАКТИРОВАТЬ .: Вот фрагмент модели:

public class ModelAgendaReceita : INotifyPropertyChanged
{

    public ModelAgendaReceita()
    {
    }

    //Here I create the model based on another model
    public ModelAgendaReceita(ModelAgendaReceita p_agendareceita)
    {
        ID = p_agendareceita.ID;
        IDFormaReceita = p_agendareceita.IDFormaReceita;
        Data = p_agendareceita.Data;
        Valor = p_agendareceita.Valor;
        Parcela = p_agendareceita.Parcela;
        Recibo = p_agendareceita.Recibo;
        Pago = p_agendareceita.Pago;
        DataPagamento = p_agendareceita.DataPagamento;
        Ativo = p_agendareceita.Ativo;
    }

    public int ID { get; set; }

    public int IDFormaReceita { get; set; }

    private DateTime m_data = new DateTime(DateTime.Today.Year, DateTime.Today.Month, DateTime.Today.Day, 0, 0, 0);
    public DateTime Data
    {
        get { return m_data; }
        set { m_data = value; OnPropertyChanged("Data"); }
    }

    private decimal m_valor;
    public decimal Valor
    {
        get { return m_valor; }
        set { m_valor = value; OnPropertyChanged("Valor"); }
    }

    private int m_parcela;
    public int Parcela
    {
        get { return m_parcela; }
        set { m_parcela = value; OnPropertyChanged("Parcela"); }
    }

    private string m_recibo = string.Empty;
    public string Recibo
    {
        get { return m_recibo; }
        set { m_recibo = value; OnPropertyChanged("Recibo"); }
    }

    private bool m_pago = false;
    public bool Pago
    {
        get { return m_pago; }
        set { m_pago = value; OnPropertyChanged("Pago"); }
    }

    private DateTime m_datapagamento = new DateTime(DateTime.Today.Year, DateTime.Today.Month, DateTime.Today.Day, 0, 0, 0);
    public DateTime DataPagamento
    {
        get { return m_datapagamento; }
        set { m_datapagamento = value; OnPropertyChanged("DataPagamento"); }
    }

    private bool m_ativo = true;
    public bool Ativo
    {
        get { return m_ativo; }
        set { m_ativo = value; OnPropertyChanged("Ativo"); }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged(string propertyName)
    {
        var changed = PropertyChanged;
        if (changed != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

Вот как я объявляю свою ViewModel и Команду внутри нее:

public class HomeVM
{
    public DelegateCommand SelecaoSolicitacao { get; set; }

    public HomeVM()
    {
        SelecaoSolicitacao = new DelegateCommand(SelecionarSolicitacao);
    }

    public void ModificarAgendaReceita(object obj)
    {
        var p_atual = (ModelAgendaReceita)obj;
        var p_inicial = ListaAgendaReceitaInicial.FirstOrDefault(l => l.ID == p_atual.ID);

        if (p_inicial != null) p_atual.Status = ModelAgendaReceita.ValidarAlteracao(p_inicial, p_atual);
    }
}

Это класс, с которым я делаю свои команды:

public class DelegateCommand : ICommand
{

    //These delegates store methods to be called that contains the body of the Execute and CanExecue methods
    //for each particular instance of DelegateCommand.
    private readonly Predicate<object> _canExecute;
    private readonly Action<object> _Execute;

    //Two Constructors, for convenience and clean code - often you won't need CanExecute
    public DelegateCommand(Action<object> execute, Predicate<object> canExecute)
    {
        _canExecute = canExecute;
        _Execute = execute;
    }

    public DelegateCommand(Action<object> execute)
      : this(execute, null)
    { }

    //CanExecute and Execute come from ICommand
    public event EventHandler CanExecuteChanged;

    public bool CanExecute(object parameter)
    {
        return _canExecute == null ? true : _canExecute(parameter);
    }

    public void Execute(object parameter)
    {
        if (!CanExecute(parameter))
            return;

        _Execute(parameter);
    }

    /// <summary>
    /// Not a part of ICommand, but commonly added so you can trigger a manual refresh on the result of CanExecute.
    /// </summary>
    public void RaiseCanExecuteChanged()
    {
        CanExecuteChanged?.Invoke(this, EventArgs.Empty);
    }

}

За которыми я следовал с https://onewindowsdev.com/2016/06/16/the-command-pattern-and-mvvm/.

Кто-нибудь знает, как обойти это? Буду признателен за любой совет / помощь!

...