IOS 上的 mvvmcross 绑定问题(适用于模拟器,但某些属性在设备上不起作用)

Posted

技术标签:

【中文标题】IOS 上的 mvvmcross 绑定问题(适用于模拟器,但某些属性在设备上不起作用)【英文标题】:Problems with mvvmcross Binding on IOS (Works on Simulator, but some properties doesn't work on the Device) 【发布时间】:2013-01-11 09:49:51 【问题描述】:

问题在于绑定到 UIBarButtonItem,代码在模拟器上工作,但在设备上,属性 Enable 不起作用并且 Clicked 工作......

textViewItem 中也存在同样的问题,但这次 text 和 enable 都不起作用。

    public partial class ProcessDetailViewController : MvxBindingTouchViewController<ProcessDetailViewModel>

    public ProcessDetailViewController (MvxShowViewModelRequest request)
        : base (request,"ProcessDetailViewController", null)
    
    

    public override void DidReceiveMemoryWarning ()
    
        // Releases the view if it doesn't have a superview.
        base.DidReceiveMemoryWarning ();

        // Release any cached data, images, etc that aren't in use.
    

    public override void ViewDidLoad ()
    
        base.ViewDidLoad ();
        this.AddBindings(
            new Dictionary<object, string>()
            
             this.lblSeguradoraNome , "'Text':'Path':'AssuranceCompanyID'" ,
             this.lblSeguradoraGestor , "'Text':'Path':'AssuranceManager'" ,
             this.lblApoliceData , "'Text':'Path':'InsurancePolicyStartDate'" ,
             this.lblApoliceNum , "'Text':'Path':'InsurancePolicyNumber'" ,
             this.lblApoliceRamo , "'Text':'Path':'InsurancePolicyBranch'" ,
             this.lblDataPedido , "'Text':'Path':'RequestDate'" ,
             this.lblGestor , "'Text':'Path':'InternalManager'" ,
             this.lblLocalRiscoCodPostal , "'Text':'Path':'InsurancedLocationAddressCityZipCode'" ,
             this.lblLocalRiscoConcelho , "'Text':'Path':'InsurancedLocationAddressCity'" ,
             this.lblLocalRiscoMorada , "'Text':'Path':'InsurancedLocationAddress'" ,
             this.lblPerito , "'Text':'Path':'Surveyer'" ,
             this.lblSeguradoCodPostal , "'Text':'Path':'InsuredPersonAddressCityZipCode'" ,
             this.lblSeguradoConcelho , "'Text':'Path':'InsuredPersonAddressCity'" ,
             this.lblSeguradoContacto , "'Text':'Path':'InsuredPersonPhone'" ,
             this.lblSeguradoMorada , "'Text':'Path':'InsuredPersonAddress'" ,
             this.lblSeguradoNome , "'Text':'Path':'InsuredPersonName'" ,
             this.btnDownload , "'Clicked':'Path':'DownloadProcessButton','Enabled':'Path':'HideIfDownloaded'" ,
             this.btnTerminarVisita , "'Clicked':'Path':'EndVisitButton','Enabled':'Path':'ShowIfOnVisit'" ,
             this.btnObterLocalizacao , "'Clicked':'Path':'AdquireLocationButton','Enabled':'Path':'ShowIfOnVisit'" ,
             this.btnIniciarVisita , "'Clicked':'Path':'BeginVisitButton','Enabled':'Path':'HideIfOnVisit'" ,
             this.btnTirarFoto , "'Clicked':'Path':'TakePhotoButton','Enabled':'Path':'ShowIfOnVisit'" ,
             this.btnVoltar , "'Clicked':'Path':'ReturnButton'" ,
             this.btnUpload , "'Clicked':'Path':'UploadProcessButton','Enabled':'Path':'CanUpload'" ,
            
        );
    //  var a= NavigationItem.LeftBarButtonItems[0].Enabled

        // Perform any additional setup after loading the view, typically from a nib.
    

    public override void ViewDidUnload ()
    
        base.ViewDidUnload ();

        // Clear any references to subviews of the main view in order to
        // allow the Garbage Collector to collect them sooner.
        //
        // e.g. myOutlet.Dispose (); myOutlet = null;

        ReleaseDesignerOutlets ();
    

    public override bool ShouldAutorotateToInterfaceOrientation (UIInterfaceOrientation toInterfaceOrientation)
    
        // Return true for supported orientations
        return true;
    
 

 public class ProcessDetailViewModel : ProcessNavigationBaseViewModel
(...)

public class ProcessNavigationBaseViewModel : BaseViewModel

    (...)

    #region Properties
    private Process _currentProcess;

    private static User _user;

    private bool _isGPSLocationStarted;

    private double _latitude;

    private double _longitude;

    private string _photoFilename = "";

    public Process CurrentProcess
    
        get
        
            return _currentProcess;
        
        set
        
            _currentProcess = value;
            FirePropertyChanged(() => CurrentProcess);
        
    

    public User User
    
        get  return _user; 
        set
        
            _user = value;
            FirePropertyChanged(() => User);
        
    

    private bool _isDownloaded
    
        get
        
            return CurrentProcess.IsLockedInServer && !(CurrentProcess.ProcessState == ProcessState.WaitingReportProduction.ToString());
        
        set
        
            CurrentProcess.IsLockedInServer = value;
            FirePropertyChanged(() => ShowIfDownloaded);
            FirePropertyChanged(() => HideIfDownloaded);
        
    

    public bool ShowIfDownloaded
    
        get  return _isDownloaded; 
    

    public bool HideIfDownloaded
    
        get  return !_isDownloaded; 
    

    public bool CanUpload
    
        get  return ( CurrentProcess.ProcessState == ProcessState.WaitingUpload.ToString()); 
    

    public bool CanDownload
    
        get  return (CurrentProcess.ProcessState != ProcessState.WaitingReportProduction.ToString() && 
                                    CurrentProcess.ProcessState == ProcessState.WaitingSurveyorAcceptionDecision.ToString()) ;  
    

    public bool ShowIfOnVisit
    
        get  return (CurrentProcess.ProcessState == ProcessState.OnVisist.ToString()); 
    

    public bool HideIfOnVisit
    
        get  return (!(CurrentProcess.ProcessState == ProcessState.OnVisist.ToString())) && ShowIfDownloaded; 
    

    public string ProcessDescription
    
        get
        
            return string.Format("0 - 1", CurrentProcess.ProcessNumber, CurrentProcess.RequestedService.RequestedServiceType);
        
    
(...)
 

提前致谢

[编辑]

应用程序输出: 2013-01-11 09:16:56.369 LinkFENACAMSIGEPMobileUIiPad[6496:c07] 导航:诊断:2.24 使用 args 导航到 MainMenuViewModel

2013-01-11 09:16:56.369 链接FENACAMSIGEPMobileUIiPad[6496:c07] TouchNavigation:诊断:2.24 导航请求

2013-01-11 09:16:56.421 链接FENACAMSIGEPMobileUIiPad[6496:c07] MvxBind:警告:2.29 Unable to bind to source is null

2013-01-11 09:16:56.423 链接FENACAMSIGEPMobileUIiPad[6496:c07] MvxBind:警告:2.29 Unable to bind to source is null

[EDIT 20130111:11:12] - 链接器行为:仅链接 SDK 程序集

类似于: MvvmCross Monotouch - Fail to bind Properties on a real iPad, but it works on the Simulator(我做不到这个……)

【问题讨论】:

【参考方案1】:

我在示例代码中看不到 barbutton - 所以我将根据 Text、Clicked、Enabled 等来回答。

如果这在模拟器中有效,但在设备上无效,则很可能与链接器有关 - 与 MvvmCross Monotouch - Fail to bind Properties on a real iPad, but it works on the Simulator 中的完全一样

要测试这个理论,请尝试将链接器转为包含所有符号


假设这是问题的原因......那么要解决它,您需要包含一个 LinkerPleaseInclude.cs 文件,该文件将诱使链接器包含这些属性。

例如,它可能看起来像:

public class LinkerIncludePlease

    private void IncludeClicked(UIButton button)
    
        button.Clicked += (s, e) =>  ;
    

    private void IncludeEnabled(UIButton button)
    
        button.Enabled = !button.Enabled;
    

    private void IncludeText(UILabel label)
    
        label.Text = label.Text + "test";
    

注意:此代码从未实际执行,而是在构建时由链接器分析。

【讨论】:

谢谢!!,我强制链接器并更改链接选项,它的工作原理! 感谢 Stuart,即使是在两年后,也挽救了我的一天。

以上是关于IOS 上的 mvvmcross 绑定问题(适用于模拟器,但某些属性在设备上不起作用)的主要内容,如果未能解决你的问题,请参考以下文章

MvvmCross.Forms - 默认 Spinner 不会退出

MvvmCross 绑定到 UIButton.TitleLabel.Text

MvvmCross 和 Android 上的链接问题

Xamarin iOS - MVVMCross:无法使用 ViewModel 中的命令连接自定义单元格中的按钮

mvvmcross xamarin.forms PictureChooser

MvvmCross 与 Xamarin.Forms 和自定义 iOS 渲染器 - 防止导航滑动 iOS - MasterDetail