具有 class 属性的 Xamarin 绑定上下文

Xamarin Binding Context with class properties

我的主页有 BindingContext 喜欢 class。

private WorkOrderDettaglioSpesa _WoSpesaDett = new WorkOrderDettaglioSpesa();
public WorkOrderDettaglioSpesa WoSpesaDett {
    get { return _WoSpesaDett; }
    set {
        _WoSpesaDett = value;
        RaisePropertyChanged(() => WoSpesaDett);
    }
}

BindingContext="{Binding .}" 就是 BindingContext.

在XAML页面中我是这样使用的:

<Label Text="{core:Translate LbLImporto}" 
       Grid.Row="0" 
       Grid.Column="0" 
       Style="{StaticResource LblDescrizione}" />         
<Entry IsEnabled="{Binding WoSpesaDett.DatiArticoloSelezionato.AbilitaImporto}" 
       Keyboard="Numeric" 
       Text="{Binding WoSpesaDett.Importo, Mode=TwoWay}" 
       Grid.Row="0"
       Grid.Column="1" >
</Entry>

在 ViewModel 中,我有一个函数,当这个条目更改它的值并检查该值时,它会触发,但该值始终是设置的第一个值。

 private void ControllaMassimale() 
 {
    if (!string.IsNullOrWhiteSpace(WoSpesaDett.LimitePerSingolaSpesa)) 
    {
        RaisePropertyChanged(() => WoSpesaDett);

        double? Massimale = Convert.ToDouble(WoSpesaDett.LimitePerSingolaSpesa);
        double? Valore = WoSpesaDett.Importo / WoSpesaDett.Quantita; // <<-- WoSpesaDett.Importo is always 0 (the default value)

        if (Valore != null && Valore > Massimale) 
        {
            WoSpesaDett.FuoriMassimale = true;
            var Params = new { 
                Titolo = "MyTitle",
                Messaggio = "MyMessaggio",
            };

            MessagingCenter.Send(Me, Costanti.ChiaviMessaggi.MessaggioGenerico.ToString(), Params);
        } 
        else
            WoSpesaDett.FuoriMassimale = false;
    }
}

我做错了什么? 为什么当输入值改变时,我的 class 中相应的 属性 没有更新?

谢谢!

编辑 - 有我的代码 classes:

WorkOrderDettaglioSpesa

public class WorkOrderDettaglioSpesa : WorkOrderDettaglioListaSpese {

    public class DatiTipoSpesa {
        public string UnitaDiMisura { get; set; } = string.Empty; // TBS TRT str1
        public bool MassimaliSiNo { get; set; } = false; // str2
        public bool AbilitaQuantita { get; set; } = false; // str3
        public string PagamentoDiDefault { get; set; } = string.Empty; // str4
        public bool AbilitaPagamento { get; set; } = true; // str5
        public bool KmSiNo { get; set; } = false; // str7
        public string CostoTRX { get; set; } = string.Empty; // str8
        public bool AbilitaImporto { get; set; } = false;// Mi serve per il template
        public bool AbilitaTipoSpesa { get; set; } = false;// Mi serve per il template
    }

    public string DaFatturare { get; set; }
    public string DaFatturareDefault { get; set; } // Serve per fare i controlli al cambio del check
    public string NotaFatturare { get; set; }
    public string LimitePerSingolaSpesa { get; set; }

    [IgnoreMapping]
    public DatiTipoSpesa DatiArticoloSelezionato { get; set; } = new DatiTipoSpesa();

    #region Installatore
    public string Installatore_Cod { get; set; }
    [IgnoreMapping]
    public Combo Installatore {
        get {
            Combo wRet = new Combo();
            if (DsInstallatore != null) wRet = DsInstallatore.Find(ele => ele.Codice == Installatore_Cod);
            return wRet;
        }
        set { if (value != null) Installatore_Cod = value.Codice; }
    }
    #endregion

    #region Tecnico
    public string Tecnico_Cod { get; set; }
    [IgnoreMapping]
    public Combo Tecnico {
        get {
            Combo wRet = new Combo();
            if (DsTecnico != null) wRet = DsTecnico.Find(ele => ele.Codice == Tecnico_Cod);
            return wRet;
        }
        set { if (value != null) Tecnico_Cod = value.Codice; }
    }
    #endregion

    #region AreaSpesa
    public string AreaSpesa_Cod { get; set; }
    [IgnoreMapping]
    public Combo AreaSpesa {
        get {
            Combo wRet = new Combo();
            if (DsAreaSpesa != null) wRet = DsAreaSpesa.Find(ele => ele.Codice == AreaSpesa_Cod);
            return wRet;
        }
        set { if (value != null) AreaSpesa_Cod = value.Codice; }
    }
    #endregion

    #region TipoSpesa
    public string TipoSpesa_Cod { get; set; }
    [IgnoreMapping]
    public Combo TipoSpesa {
        get {
            Combo wRet = new Combo();
            if (DsTipoSpesa != null) wRet = DsTipoSpesa.Find(ele => ele.Codice == TipoSpesa_Cod);
            return wRet;
        }
        set { if (value != null) TipoSpesa_Cod = value.Codice; }
    }
    #endregion

    #region Valuta
    public string Valuta_Cod { get; set; }
    [IgnoreMapping]
    public Combo Valuta {
        get {
            Combo wRet = new Combo();
            if (DsValuta != null) wRet = DsValuta.Find(ele => ele.Codice == Valuta_Cod);
            return wRet;
        }
        set { if (value != null) Valuta_Cod = value.Codice; }
    }
    #endregion

    #region TipoPagamento
    public string TipoPagamento_Cod { get; set; }
    [IgnoreMapping]
    public Combo TipoPagamento {
        get {
            Combo wRet = new Combo();
            if (DsTipoPagamento != null) wRet = DsTipoPagamento.Find(ele => ele.Codice == TipoPagamento_Cod);
            return wRet;
        }
        set { if (value != null) TipoPagamento_Cod = value.Codice; }
    }
    #endregion

    #region DataSource Combo
    [IgnoreMapping]
    public List<Combo> DsInstallatore { get; set; }

    [IgnoreMapping]
    public List<Combo> DsTecnico { get; set; }

    [IgnoreMapping]
    public List<Combo> DsAreaSpesa { get; set; }

    [IgnoreMapping]
    public List<Combo> DsTipoSpesa { get; set; }

    [IgnoreMapping]
    public List<Combo> DsValuta { get; set; }

    [IgnoreMapping]
    public List<Combo> DsTipoPagamento { get; set; }
    #endregion
}

WorkOrderDettaglioListaSpese

public class WorkOrderDettaglioListaSpese : BaseModel {
    public DateTime? DataSpesa { get; set; }

    public string InstallatoreTecnico {
        get {
            return string.Join(" ", _Installatore, _Tecnico);
        }
    }

    public string TipoSpesaDescrizione { get; set; } // codart_descr
    public string SpesaValore {
        get {
            return $"{SpeseViaggioDescrizione} {Quantita}";
        }
    }

    public string SpesaImporto {
        get {

            string wRet = string.Empty;

            string FuoriMassimaleTemplate = "FUORI-MAX";
            string NoCambioTemplate = "NO-CAMBIO";

            if (FuoriMassimale) {
                wRet = $"{Importo?.ToString("F2")} {ValutaDescrizione} {FuoriMassimaleTemplate}";
            } else {
                wRet = $"{Importo?.ToString("F2")} {ValutaDescrizione}";
            }

            if (NoCambio) wRet += $" {NoCambioTemplate}";

            return wRet;
        }
    }

    public string SpeseViaggioDescrizione { get; set; } // cod_trt_descr
    public string ValutaDescrizione { get; set; } // cod_val_descr

    public double? Quantita { get; set; } = 1; // qta
    public double? Importo { get; set; }

    public string _Installatore { get; set; }
    public string _Tecnico { get; set; }
    public bool Rimborsata { get; set; }
    public bool FuoriMassimale { get; set; }
    public bool NoCambio { get; set; }
}

基础模型

public class BaseModel {
    internal TranslateExtension ts = new TranslateExtension();

    public string Cod_div { get; set; }
    public string Cod_soc { get; set; }
    public string Cod_fil { get; set; }
    public string Guid_servizio { get; set; }
    public string FlagTratt { get; set; }

    public bool IsNew {
        get {
            return string.IsNullOrWhiteSpace(Guid_servizio);
        }
    }

    internal class FiltroAttribute : Attribute { }
    internal class IgnoreMappingAttribute : Attribute { }


    private static IEnumerable<T> ReflectionFilter<T>(IEnumerable<T> collection, string property, object value) {
        if (collection.Count() == 0) return new List<T>();

        PropertyInfo pInfo = collection.First().GetType().GetProperty(property);

        return collection.Where(c => ((string)pInfo.GetValue(c))?.IndexOf((string)value, StringComparison.InvariantCultureIgnoreCase) > -1).ToList();
    }

    public static List<T> FiltraListaTipizzata<T>(List<T> ListaDaFiltrare, string Filtro) {
        try {
            List<T> wRet = new List<T>();
            Type Classe = typeof(T);
            List<PropertyInfo> PropToFilter = Classe.GetProperties().Where(prop => Attribute.IsDefined(prop, typeof(FiltroAttribute))).ToList();

            // TODO: Da ottimizzare e cercare di utilizare il PredicateBuilder
            if (string.IsNullOrWhiteSpace(Filtro)) {
                wRet = ListaDaFiltrare;
            } else {
                foreach (PropertyInfo Prop in PropToFilter) {
                    IEnumerable<T> TmpList = ReflectionFilter(ListaDaFiltrare, Prop.Name, Filtro);
                    wRet = wRet.Union(TmpList).ToList();
                }
            }

            return wRet;
        } catch (Exception ex) {

            throw ex;
        }
    }

}

您的 class WoSpesaDett 确实继承自 INPC。但是,当 class 中的 property 发生变化时,这不会更新视图。 WoSpesaDett 中的属性必须调用 INotifyPropertyChanged 事件。

所以像这样:

public class WoSpesaDett : INotifyPropertyChanged
{

    private string importo;
    public string Importo
    {
        get { return fuoriMassimale; }
        set
        { 
            fuoriMassimale = value;
            OnPropertyChanged();
        }
    }
}