【问题标题】:How to call a function in an another view controller in Xamarin.ios?如何在 Xamarin.ios 的另一个视图控制器中调用函数?
【发布时间】:2020-11-05 10:43:40
【问题描述】:

我有一个名为LeftViewController 的控制器,它代表我的主控制器ViewController 的侧边菜单。当我单击侧面菜单中的按钮时,我希望调用主 ViewController 中的函数并更改按钮的标题。我试图在ViewController.cs 中定义一个类refresh_all 来负责更新我的按钮的标题,然后我会从那里定义一个来自ViewController 的对象来调用它的函数。

 public  class refresh_all{


        ViewController v1 = new ViewController();

        public void refresh_components()
        {


            v1.refresh_ac(); //

        }

    }

ViewController 类中的函数:

 public void refresh_ac()
        {
            s2.SetTitle(CommonClass.value.ToString(), UIControlState.Normal);//s2 is my button name
        }

我在LeftViewController 控制器中定义了来自refresh_all 类的对象,如下所示:

    partial void Conbtn_TouchUpInside(UIButton sender)
        {

            refresh_all r1 = new refresh_all();

            r1.refresh_components();

        }

s2.SetTitle(CommonClass.value.ToString(), UIControlState.Normal); 出现错误 说Object reference not set to an instance of an object

非常感谢您的帮助。

【问题讨论】:

    标签: c# ios xamarin xamarin.ios event-handling


    【解决方案1】:

    您能否检查一下 s2 按钮对象和 CommonClass 对象。 "CommonClass.value" 这里的CommonClass应该是调用属性的类的实例/对象。

    在 LeftViewController 中发送 ViewController 对象,然后发送到 refresh_all 类。

    【讨论】:

    • CommonClass 是一个静态类,具有静态属性
    • 能否提供异常的完整堆栈跟踪?
    • 这是说 s2 是 (null) 。
    • ViewController 中的控件是否使用了其他对象?
    • 这就是您遇到异常的原因。您必须初始化 s2 按钮。
    【解决方案2】:

    活动

    我设法让事件方法正常工作。我的信息基于以下链接:

    在我的UITableViewController(视图控制器 B)中,我添加了以下内容:

    // class variable  
    public event EventHandler<BLevelSelectedEventArgs> BLevelSelected;
    
    // event handler
    public class BLevelSelectedEventArgs : EventArgs
    {
        public BLevelItem bLevel { get; set; }
    
        public BLevelSelectedEventArgs(BLevelItem bLevel) : base()
        { 
            this.bLevel = bLevel;
        }
    }
    

    这里定义了事件以及自定义事件处理程序。您可以定义要使用事件传输数据的属性,例如细绳。这里使用了自定义的BLevelItem。应为您的应用程序更改事件处理程序的名称和事件的名称。在这个UITableViewController 类中,我还定义了UITableViewSource

    public override void RowSelected (UITableView tableView, NSIndexPath indexPath)
    {
        tableView.DeselectRow (indexPath, true); // iOS convention is to remove the highlight
    
        if (this.controller.BLevelSelected != null) {
            this.controller.BLevelSelected (this, new BLevelSelectedEventArgs (controller.bLevelList[indexPath.Row]));
        }
    
    }
    

    这里引发了事件,并与事件一起传递了参数。现在只缺少一个对事件做出反应的侦听器。这在视图控制器 A 上进行:

    bLevelController.BLevelSelected += (object sender, BLevelController.BLevelSelectedEventArgs e) => {
        System.Diagnostics.Debug.WriteLine(e.bLevel.bLevelName);
    };
    

    bLevelController 是我的视图控制器 B 的一个实例。您可以如上所示访问定义的事件,但您必须注意您使用类名 (BLevelController) 来访问 BLevelSelectedEventArgs

    如果您还可以添加其他可能性来在视图控制器(通知中心、协议/委托等)之间传递数据,那就太好了。


    委托

    使用了一种委托方法Part 5 - Working with Tables in the iOS Designer。您在 UITableViewController 中定义了一个 Delegate

    public MasterViewController Delegate {get;set;} // will be used to Save, Delete later
    

    当您在 MasterViewController 中实例化 DetailViewController 时,您设置了 Delegate 属性。示例:

    public override void PrepareForSegue (UIStoryboardSegue segue, NSObject sender)
    {
        base.PrepareForSegue (segue, sender);
    
        var detailViewController = segue.DestinationViewController as DetailViewController;
    
        if (detailViewController != null) {
            detailViewController.Delegate = this;
        }
    }
    

    DetailViewController中你可以调用MasterViewController中的任何方法:

    public override void RowSelected (UITableView tableView, NSIndexPath indexPath)
        {
        tableView.DeselectRow (indexPath, true); // iOS convention is to remove the highlight
        if (this.controller.Delegate != null) {
            this.controller.Delegate.SetItems (this.controller.items[indexPath.Row]);
        }
    }
    
    // a method in MasterViewController
    public void SetItems(string items){
        this.items = items;
        this.NavigationController.PopViewControllerAnimated (true);
        // do something here
    }
    

    这行得通,因为我将 DetailViewController 传递给 DetailViewSource

    // in ViewDidLoad of DetailViewController
    this.TableView.Source = new DetailViewSource (this);
    
    // in the constructor of DetailViewSource
    private CostCentreController controller;
    
    public CostCentreListSource (CostCentreController controller)
    {
        this.controller = controller;
    }
    

    NSNotificationCenter

    我的信息基于xamarin/monotouch-samplesXamarin NSNotificatioCenter: How can I get the NSObject being passed?

    没有数据传输的简单示例:

    // class level variable
    NSObject observer;
    
    // register as observer
    public override void ViewWillAppear (bool animated)
    {
        base.ViewWillAppear (animated);
        observer = NSNotificationCenter.DefaultCenter.AddObserver ((NSString)UIDevice.OrientationDidChangeNotification, OrientationChanged);
    }
    
    // deregister as observer
    public override void ViewDidDisappear (bool animated)
    {
        base.ViewDidDisappear (animated);
        if (observer != null) { 
            NSNotificationCenter.DefaultCenter.RemoveObserver (observer);
            observer = null;
        }
    }
    
    // function which should do something when notification is received
    public void OrientationChanged(NSNotification notification){
        Console.WriteLine ("test");
        // perhaps you can do the following as in the linked SO question: NSObject myObject = notification.Object;
    }
    

    参考here

    【讨论】:

      猜你喜欢
      • 2017-03-12
      • 1970-01-01
      • 2020-02-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-23
      相关资源
      最近更新 更多