0

I have a Page that have BindingContext like a class.

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

BindingContext="{Binding .}" is the BindingContext.

In the XAML page I use this in this way:

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

Inside the ViewModel I have a function that is trigger where this Entry changed it's value and check the value, but the value is always the first value setted.

 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;
    }
}

What I'm doing wrong? Why when the value of the input change, the respective property in my class isn't updated?

Thank you!

EDIT - There are my code 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; }
}

BaseModel

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;
        }
    }

}
Hikari
  • 589
  • 7
  • 29
  • If WoSpesaDett is your BindingContext then you just have to write `Entry IsEnabled="{Binding DatiArticoloSelezionato.AbilitaImporto}"`, same goes for `Text="{Binding Importo, Mode=TwoWay}"` – Csharpest Dec 18 '17 at 15:01
  • Thanks for the reply! Sorry, my BindingContext is: BindingContext="{Binding .}" – Hikari Dec 18 '17 at 15:22

1 Answers1

1

Your class WoSpesaDett does inherit from INPC. But that doesn't update the View when a property inside the class changes. Your properties in WoSpesaDett must call the INotifyPropertyChanged event.

So something like this:

public class WoSpesaDett : INotifyPropertyChanged
{

    private string importo;
    public string Importo
    {
        get { return fuoriMassimale; }
        set
        { 
            fuoriMassimale = value;
            OnPropertyChanged();
        }
    }
}
Csharpest
  • 1,258
  • 14
  • 32
  • Thank you. But my class has many properties, I must do this for each property? – Hikari Dec 18 '17 at 15:46
  • Yes, you must do this for each property that you want to keep updated by the view – Csharpest Dec 18 '17 at 15:47
  • But others property changes correctly. It can be because the propery "importo" is declared in the base class of WoSpesaDett? The type of WoSpesaDett is WorkOrderDettaglioSpesa that derived by WorkOrderDettaglioListaSpese and "importo" is in WorkOrderDettaglioListaSpese class. – Hikari Dec 18 '17 at 15:51
  • Oh yeah, i didnt realize this was the instance name instead of the type name. You should really just post your code of the class. I'll be offline for about 40 min, cu then – Csharpest Dec 18 '17 at 15:53
  • Maybe the problem is triggered because the property is Nullable? (It's type is double?) – Hikari Dec 18 '17 at 16:52
  • This might be, but it implicitly binds to the ToString() if u bind a double or int. But like i said, you have to implement INPC and call it for every property that should be updated for the view – Csharpest Dec 18 '17 at 18:13