具有 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();
}
}
}
我的主页有 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();
}
}
}