MonoTouch 实例分析

shared application那些就不说了 前面已经说过了 这里主要说的是container的实现。

IMPLEMENTING AN IOS PLATFORM CONTAINER

因为之前有iOS开发经验,所以用cocoa和MonoTouch来对应 还是比较简单的

Initializing a Container in MonoTouch

iOS AppDelegate.cs
namespace CustomerManagement.Touch
{
  [MXTouchTabletOptions(TabletLayout.MasterPane, 
    MasterShowsinLandscape = true, 
    MasterShowsinPotrait = true, 
    AllowDividerResize = false)]
  [MXTouchContainerOptions(SplashBitmap = “Images/splash.jpg”)]
  [Register (“AppDelegate”)]
  public partial class AppDelegate : UIApplicationDelegate
  {
    UIWindow window;
    public override bool FinishedLaunching (UIApplication app, NSDictionary options)
    {
      // create a new window instance based on the screen size
      window = new UIWindow (UIScreen.MainScreen.Bounds);
      MXTouchContainer.Initialize(new CustomerManagement.App(), this, window);
      // add Views
      MXTouchContainer.AddView<List<Customer>>(typeof(CustomerListView),
        ViewPerspective.Default);
      MXTouchContainer.AddView<Customer>(typeof(CustomerView),
        ViewPerspective.Default);
      MXTouchContainer.AddView<Customer>(typeof(CustomerEditView),
        ViewPerspective.Update);
      MXTouchContainer.Navigate(null, MXContainer.Instance.App.NavigateOnLoad);
      UIDevice.CurrentDevice.BeginGeneratingDeviceOrientationNotifications();
      return true;
    }
  }
}

如果不定义这个container的一些属性的话,这个程序在ipad上运行的效果和iphone是一样的,这样UE肯定不好,所以在这里使用MXTouchTabletOptions来设置一些属性。

Building the Customer List View in MonoTouch

MonoCross provides three base classes from which to derive your views:
MXTouchViewController: A basic view with no functionality that is derived directly from UIViewController. It is intended to contain basic views and show the minimal functional-ity needed for a view in the Touch container. Possible uses include placing a UIImageView to show an image, or your own  UIView-derived class.
  MXTouchTableViewController: A  UITableViewController-derived class for implementing lists and tables. You can use this class to build your Customer List View.
  ‹ MXTouchDialogViewController: A view derived from  DialogViewController, an open source project built and maintained by Miguel de Icaza. This class indirectly derives from  UITableViewController  and builds dialog-like views generally found in the iPhone and iPad Settings app. Your Customer View and Customer Edit View use this view class as its base.

下面是MonoTouch的tableView实例
namespace CustomerManagement.Touch
{
  [MXTouchViewAttributes(ViewNavigationContext.Master)]
  public class CustomerListView : MXTouchTableViewController<List<Customer>>
  {
    public CustomerListView()
    {
    }
    public override void Render()
    {
      Title = “Customers”;
      TableView.Delegate = new TableViewDelegate(this, Model);
      TableView.DataSource = new TableViewDataSource(Model);
      TableView.ReloadData();
      if (MXTouchNavigation.MasterDetailLayout && Model.Count > 0)
      {
        // we have two available panes, fill both (like the email application)
         this.Navigate(string.Format(“Customers/{0}”, Model[0].ID));
      }
    }
    public override void ViewDidLoad()
    {
      base.ViewDidLoad();
      NavigationItem.SetRightBarButtonItem(
        new UIBarButtonItem(UIBarButtonSystemItem.Add,
          (sender, e) => { NewCustomer(); }), false);
    }
    public void NewCustomer()
    {
      MXTouchContainer.Navigate(this, “Customers/NEW”);
    }
    public override void ViewWillAppear(bool animated)
    {
    }
    public override bool ShouldAutorotateToInterfaceOrientation(
      UIInterfaceOrientation toInterfaceOrientation)
    {
      return true;
    }
    private class TableViewDelegate : UITableViewDelegate
    {
      private CustomerListView _parent;
      private List<Customer> _clientList;
      public TableViewDelegate(CustomerListView parent, List<Customer> list)
      {
        _parent = parent;
        _clientList = list;
      }
      public override void RowSelected(UITableView tableView, NSIndexPath indexPath)
      {
        Customer client = _clientList[indexPath.Row];
         _parent.Navigate(String.Format(“Customers/{0}”, client.ID));
      }
    }
    private class TableViewDataSource : UITableViewDataSource
    {
      static NSString kCellIdentifier = new NSString(“ClientCell”);
      private List<Customer> _list;
      public TableViewDataSource(List<Customer> list)
      {
        this._list = list;
      }
      public override int RowsInSection(UITableView tableview, int section)
      {
        return _list.Count;
      }
      public override UITableViewCell GetCell(UITableView tableView,
        NSIndexPath indexPath)
      {
        UITableViewCell cell = tableView.DequeueReusableCell(kCellIdentifier);
        if (cell == null)
        {
          cell = new UITableViewCell(UITableViewCellStyle.Subtitle, kCellIdentifier);
          if (!MXTouchNavigation.MasterDetailLayout)
            cell.Accessory = UITableViewCellAccessory.DisclosureIndicator;
          else
            cell.Accessory = UITableViewCellAccessory.None;
        }
        cell.TextLabel.Text = _list[indexPath.Row].Name;
        cell.DetailTextLabel.Text = _list[indexPath.Row].Website;
        return cell;
      }
      public override string TitleForHeader(UITableView tableView, int section)
      {
        return string.Empty;
      }
      public override int NumberOfSections(UITableView tableView)
      {
        return 1;
      }
    }
  }
}

从上面看出,render方法主要设置tableview的属性,并且要调用reloaddata来刷新数据,viewDidLoad主要是对界面进行定义。其他的实现和cocoa的几乎是对应的没什么好说的。
运行的效果是下面这样滴

Building the Customer View in MonoTouch

namespace CustomerManagement.Touch
{
  [MXTouchViewAttributes(ViewNavigationContext.Detail)]
  public class CustomerView : MXTouchDialogView<Customer>
  {
    public CustomerView()
      : base(UITableViewStyle.Grouped, null, true)
    {
    }
    public override void ViewDidLoad()
    {
      base.ViewDidLoad();
      NavigationItem.SetRightBarButtonItem(
        new UIBarButtonItem(UIBarButtonSystemItem.Action,
          (sender, e) => { ActionMenu(); }), false);
    }
    public override void Render()
    {
      string addressString = Model.PrimaryAddress != null ?
        Model.PrimaryAddress.ToString() : string.Empty;
      this.Root = new RootElement(“Customer Info”)
      {
        new Section(“Contact Info”)
        {
          new StringElement(“ID”, Model.ID),
          new StringElement(“Name”, Model.Name ?? string.Empty),
          new StringElement(“Website”, Model.Website ?? string.Empty,
            delegate { LaunchWeb();}),
          new StringElement(“Primary Phone”, Model.PrimaryPhone ?? string.Empty,
            delegate { LaunchDial();})
        },
        new Section(“General Info”)
        {
          new StyledMultilineElement(“Address”, addressString,
            UITableViewCellStyle.Subtitle,
              delegate { LaunchMaps(); } ),
          new StringElement(“Previous Orders “, Model.Orders != null ?
             Model.Orders.Count.ToString() : string.Empty),
          new StringElement(“Other Addresses “, Model.Addresses != null ?
             Model.Addresses.Count.ToString() : string.Empty),
          new StringElement(“Contacts “, Model.Contacts != null ?
             Model.Contacts.Count.ToString() : string.Empty),
        },
      };
    }
    void ActionMenu()
    {
      //_actionSheet = new UIActionSheet(“”);
      UIActionSheet actionSheet = new UIActionSheet(
        “Customer Actions”, null, “Cancel”, “Delete Customer”,
           new string[] { “Change Customer” });
      actionSheet.Style = UIActionSheetStyle.Default;
      actionSheet.Clicked += delegate(object sender, UIButtonEventArgs args)
      {
        switch (args.ButtonIndex)
        {
          case 0: DeleteCustomer(); break;
          case 1: ChangeCustomer(); break;
        }
      };
      if (UIDevice.CurrentDevice.UserInterfaceIdiom == UIUserInterfaceIdiom.Phone)
        actionSheet.ShowFromToolbar(NavigationController.Toolbar);
      else
        actionSheet.ShowFrom(NavigationItem.RightBarButtonItem, true);
    }
    void ChangeCustomer()
    {
      this.Navigate(string.Format(“Customers/{0}/EDIT”, Model.ID));
    }
    void DeleteCustomer()
    {
      var alert = new UIAlertView(“Delete Client”,”Are you sure?”,null,”OK”,”Cancel”);
      alert.Show();
      alert.Clicked += (sender, buttonArgs) =>
      {
        if (buttonArgs.ButtonIndex == 0)
        {
          this.Navigate(string.Format(“Customers/{0}/DELETE”, Model.ID));
        }
      };
    }
    void LaunchWeb()
    {
      UIApplication.SharedApplication.OpenUrl(new NSUrl(Model.Website));
    }
    void LaunchMaps()
    {
      string googleAddress = string.Format(“{0} {1}\n{2}, {3}  {4}”,
            Model.PrimaryAddress.Street1, Model.PrimaryAddress.Street2,
            Model.PrimaryAddress.City, Model.PrimaryAddress.State,
            Model.PrimaryAddress.Zip);
      googleAddress = System.Web.HttpUtility.UrlEncode(googleAddress);
      string url = string.Format(“http://maps.google.com/maps?q={0}”, googleAddress);
      UIApplication.SharedApplication.OpenUrl(new NSUrl(url));
    }
    void LaunchDial()
    {
      string url = string.Format(“tel:{0}”, Model.PrimaryPhone);
      UIApplication.SharedApplication.OpenUrl(new NSUrl(url));
    }
    void ViewOrders()
    {
    }
    void NewOrder()
    {
    }
  }
}

最开始设定了[MXTouchViewAttributes(ViewNavigationContext.Detail)]属性,是为了在ipad显示的时候,可以和前面的customerList相对应,在那个view中设置的是Master,这就保证了在ipad上显示的时候,会以splitView的方式显示
其他的都是对相应的控件进行定义和操作, 对iOS熟悉的话 这个很容易看懂,如果对controller的一些代码不知道是什么的话 可以看上一篇文章,显示的效果如下



Building the Customer Edit View in MonoTouch

The final view is nearly identical to the last with two exceptions. First, replacing the label elements with data entry elements allows the user to change the values of the       fields you give them access to. Secondly, you need to keep references to the elements so that you can update the model and save it. 
namespace CustomerManagement.Touch
{
  [MXTouchViewAttributes(ViewNavigationContext.Detail)]
  public class CustomerEditView : MXTouchDialogView<Customer>
  {
    EntryElement _nameEntry;
    EntryElement _webEntry;
    EntryElement _phoneEntry;
    EntryElement _address1Entry;
    EntryElement _address2Entry;
    EntryElement _cityEntry;
    EntryElement _stateEntry;
    EntryElement _zipEntry;
    public CustomerEditView()
      : base(UITableViewStyle.Grouped, null, true)
    {
    }
    public override void ViewDidAppear(bool animated)
    {
      base.ViewDidAppear(animated);
      this.NavigationItem.SetRightBarButtonItem(
        new UIBarButtonItem(“Save”, UIBarButtonItemStyle.Done, null), false);
      this.NavigationItem.RightBarButtonItem.Clicked += delegate
      {
        SaveCustomer();
      };
      this.NavigationItem.SetLeftBarButtonItem(
        new UIBarButtonItem(“Cancel”, UIBarButtonItemStyle.Bordered, null), false);
      this.NavigationItem.LeftBarButtonItem.Clicked += delegate
      {
        if (string.Equals(“0”, Model.ID))
          this.Navigate(string.Format(“Customers”, Model.ID));
        else
          this.Navigate(string.Format(“Customers/{0}”, Model.ID));
      };
    }
    public override void Render()
    {
      if (Model.PrimaryAddress == null)
        Model.PrimaryAddress = new Address();
      _nameEntry = new EntryElement(“Name”, “Name”, Model.Name ?? string.Empty);
      _webEntry = new EntryElement(“Website”, “Website”, Model.Website ?? string.Empty);
      _phoneEntry = new EntryElement(“Primary Phone”, “Phone”,
         Model.PrimaryPhone ?? string.Empty);
      _address1Entry = new EntryElement(“Address”, “”,
         Model.PrimaryAddress.Street1 ?? string.Empty);
      _address2Entry = new EntryElement(“Address2”, “”,
         Model.PrimaryAddress.Street2 ?? string.Empty);
      _cityEntry = new EntryElement(“City “, “”,
         Model.PrimaryAddress.City ?? string.Empty);
      _stateEntry = new EntryElement(“State “, “”,
         Model.PrimaryAddress.State ?? string.Empty);
      _zipEntry = new EntryElement(“ZIP”, “”, Model.PrimaryAddress.Zip ?? string.Empty);
      this.Root = new RootElement(“Customer Info”)
      {
        new Section(“Contact Info”)
        {
          new StringElement(“ID”, Model.ID ?? string.Empty),
            _nameEntry,
            _webEntry,
            _phoneEntry,
        },
        new Section(“Primary Address”)
        {
          _address1Entry,
          _address2Entry,
          _cityEntry,
          _stateEntry,
          _zipEntry,
        },
      };
    }
    void SaveCustomer()
    {
      Model.Name = _nameEntry.Value;
      Model.Website = _webEntry.Value;
      Model.PrimaryPhone = _phoneEntry.Value;
      Model.PrimaryAddress.Street1 = _address1Entry.Value;
      Model.PrimaryAddress.Street2 = _address2Entry.Value;
      Model.PrimaryAddress.City = _cityEntry.Value;
      Model.PrimaryAddress.State = _stateEntry.Value;
      Model.PrimaryAddress.Zip = _zipEntry.Value;
      // Save
      if (string.Equals(Model.ID, “0”))
        this.Navigate(string.Format(“Customers/{0}/CREATE”, Model.ID));
      else
        this.Navigate(string.Format(“Customers/{0}/UPDATE”, Model.ID));
    }
  }
}

下面是效果图
从上面的代码可以看出 customerView 和 customerEditView 依附的controller是同一个(不知道controller长什么样的,可以看回前一篇文章),这样就减少了多写一个controller的时间,让代码精简了,也最大程度地利用了先用的controller。也是共享概念的体现。

我觉得在已经对iOS有一定的开发经验的基础上再看看MonoTouch确实很容易上手,而且觉得C#实现起来比objective-c更加灵活。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值