MVVMLight事件到命令,模型作为命令参数

时间:2018-11-07 13:45:58

标签: c# binding uwp mvvm-light

例如,我一直试图使用MVVMLight的“事件到命令”功能将ViewModel中的命令链接到诸如TextBox中的TextChanged之类的事件。在UWP中,事件到命令会自动假定命令参数是TextChanged的事件args。我不需要,我想发送一个模型作为命令参数,像这样:

<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/>

编辑:该文本框是ListView内DataTemplate的一部分。我已经编辑了代码块以更清楚地反映这一点。我还提供了相同的示例,但CalendarDatePicker却总是失败,无法将模型作为命令参数发送,而是发送了eventargs。

<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是一个简单的Converter,它处理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,该模型是提供给ListView的ItemsSource的模型。发送给Command的事件不断传递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和Command的方式:

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/开始关注。

有人知道该如何解决吗?任何建议/帮助将不胜感激!

0 个答案:

没有答案