У меня есть контроллер A, где я получаю некоторые значения. При определенных обстоятельствах пользователь должен выбрать значение, если доступно несколько. Поэтому я представляю другой контроллер представления B (UITableView), где я позволяю пользователю выбирать запись. Как я могу вызвать метод из A, когда я сейчас на B? (во избежание дублирования кода) И как передать некоторые параметры в этом методе?
Я читал о делегатах/протоколах, событиях (стиль.NET) и центре уведомлений. Каков наилучший способ передать строку и вызвать метод из A? Не могли бы вы привести пример? В примере из Xamarin нет примера того, как определить собственный протокол.
Или я должен сделать поле из A public и передать это поле для просмотра контроллера B, где я работаю с данными?
Мне удалось активировать мероприятие. Моя информация была основана на следующих ссылках:
В моем 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
.
Было бы неплохо, если бы вы могли добавить другие возможности для передачи данных между контроллерами представлений (Notification Center, Protocol/Delegates,...).
Используется метод делегата. Часть 5 - Работа с таблицами в iOS Designer. Вы определяете делегата в своем UITableViewController
:
public MasterViewController Delegate {get;set;} // will be used to Save, Delete later
Когда вы создаете экземпляр DetailViewController в MasterViewController, вы устанавливаете свойство 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;
}
Моя информация основана на xamarin/monotouch-samples и Xamarin NSNotificatioCenter: Как я могу передать NSObject? ,
Простой пример без передачи данных:
// 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;
}