C#(Xamarin iOS) How to navigate from UITableView to other ViewController? - c#

What line of code should I put inside of RowSelected?
I already used this but no luck at all :/ .
public override void RowSelected(UITableView tableView, NSIndexPath indexPath)
{
var window = UIApplication.SharedApplication.KeyWindow;
var vc = window.RootViewController;
while (vc.PresentedViewController != null)
{
vc = vc.PresentedViewController;
}
mainnearmisses myTarget = (UIViewController)vc.Storyboard.InstantiateViewController("mnearm") as mainnearmisses;
myTarget.email = locations[indexPath.Row].shopname + "";
vc.PresentViewController(myTarget, true, null);
}

Some suggestions for you.
1. Set the ViewController itself as parameter in the initializing constructor of the dataSource.
in ViewController
this.TableView.Source = new TableSource(tableItems.ToArray(), this);
in dataSource
ViewController owner;
public TableSource (string[] items, ViewController owner)
{
tableItems = items;
this.owner = owner;
}
this can make your code easy to navigation to another VC.
just use this instead of looking for current vc on Windows .
this.owner.PresentViewController(myTarget, true, null);
2. If your tableView fills with the screen , you can change your ViewController to UITableViewController.
since it inherits form IUITableViewDataSource , so it can handle the event(i.e. that method create the tableView) in its own class.
3.As I mentioned above ,check if that viewController exists
check the storyboard id and find the corresponding viewController in your project.

Related

UITableviewCell GetCell is not being called

I am using Visual Studio Community 2017 for Mac. I have a UITableview named SchoolSchedule. I am setting the Source from a button, but then when I click the button GetCell is not called, however, RowsInSection is called.
Here is my class:
public class ScheduleTableViewSource : UITableViewSource
{
private Schedule[] school;
public ScheduleTableViewSource(Schedule[] school)
{
this.school = school;
}
public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
{
var cell = (ScheduleCell) tableView.DequeueReusableCell("cell_id", indexPath);
var school1 = school[indexPath.Row];
cell.Updatecell(school1);
cell.TextLabel.Text = school[indexPath.Row].Site;
return cell;
}
public override nint RowsInSection(UITableView tableview, nint section)
{
return school.Length;
}
}
here is my button code :
partial void Get_button_TouchUpInside(UIButton sender)
{
bool check = NetworkInterface.GetIsNetworkAvailable();
if(check)
{
Service1 client = new Service1();
var school = client.CypressRidge("CypressRidge");
SchoolSchedule.Source = new ScheduleTableViewSource(school);
SchoolSchedule.ReloadData();
}
else{
Console.Write("Error no Internet connection");
return;
}
// int stop =0;
}
I have checked and there is data coming in from my service. so that is not the problem. can anyone help?
I had to deleted the table and make a new one.
there a bug in Xamarin.
I had the same problem and I managed to fix it setting up Identifier property of TableView first prototype row - in storyboard
In addition to implementing the IUITableViewDelegate and IUITableViewDataSource interfaces in the .cs file, calling RegisterNibForCellReuse, and assigning the table view's EstimatedRowHeight, it's easy to forget to set the data source and delegate properties of the table view in the XIB.

AlertFragments with android support v4 library

I'm trying to create custom AlertDialog but I have one problem.
My alert dialog class below:
class AddNewDayAlert : DialogFragment
{
public static AddNewDayAlert NewInstance(Bundle bundle)
{
AddNewDayAlert fragment = new AddNewDayAlert();
fragment.Arguments = bundle;
return fragment;
}
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
// Use this to return your custom view for this Fragment
View view = inflater.Inflate(Resource.Layout.AddNewDayLayout, container, false);
Button btn = view.FindViewById<Button>(Resource.Id.dialog_text);
EditText txt = view.FindViewById<EditText>(Resource.Id.dialog_text);
btn.Click += delegate
{
string day_name;
if (txt.Text != "" && txt.Text != null)
{
day_name = txt.Text;
Toast.MakeText(this.Activity, "Sėkmingai pridėta!!!", ToastLength.Long).Show();
Dismiss();
}
else
Toast.MakeText(this.Activity, "Pamiršote įvesti dienos pavadinimą!", ToastLength.Long).Show();
};
return view;
}
}
and problem is here:
Android.Support.V4.App.FragmentTransaction ft = FragmentManager.BeginTransaction();
Fragment prev = FragmentManager.FindFragmentByTag("dialog");
if (prev != null)
{
ft.Remove(prev);
}
ft.AddToBackStack(null);
AddNewDayAlert fragmentas = AddNewDayAlert.NewInstance(null);
fragmentas.Show(ft, "dialog");
In the last line I get an error because fragmentas.Show() is using Android.App.FragmentTransaction and I am using Android.Support.V4.App.FragmentTransaction.
If I try to use Android.App.FragmentTransaction I get error in first line:
Maybe there is way to convert? What should I do ?
You are conflicting two different FragmentTransaction classes. If you decide to use Support v4 Fragments, then you will want to use the Support v4 FragmentTransaction.
https://developer.android.com/reference/android/app/FragmentTransaction.html
https://developer.android.com/reference/android/support/v4/app/FragmentTransaction.html
You will also need to ensure that you are using a AppCompatActivity(Which inherits FragmentActivity and has a reference to Android.Support.V4.App.FragmentManager) if you go down the v4 route. That way you will have access to SupportFragmentManager that is the same type.
EX:
[Activity(Label = "App7", MainLauncher = true, Icon = "#drawable/icon")]
public class MainActivity : AppCompatActivity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
// Set our view from the "main" layout resource
// SetContentView (Resource.Layout.Main);
Android.Support.V4.App.FragmentTransaction ft = SupportFragmentManager.BeginTransaction();
}
}
Your AddNewDayAlert class should also inherit from V4 DialogFragment
class AddNewDayAlert : Android.Support.V4.App.DialogFragment

Monotouch UIPickerView ValueChange Event for ViewController

I want to get event in case UIPickerView changes value in any of its component, so that my UIViewController can make changes to Labels. I have come across only one helpful method provided by PickerView model:
public override void Selected(UIPickerView pickerView, nint row, nint component)
When anything changes, there are corresponding changes reflected in model. But what should I do in case I want to reflect those changes back to ViewController? I want to do the job exactly like Delegates do in iOS. I am not much familiar with c#. Any help appreciated. Thanks.
public partial class ViewController : UIViewController
{
public override void ViewDidLoad()
{
base.ViewDidLoad();
// Perform any additional setup after loading the view, typically from a nib.
setupHandlers();
}
void setupHandlers()
{
pickerModel = new UnitPickerViewModel();
pickerModel.Items = lengthArray;
pickerModel.setDataForSecondComponent(lengthArray2);
pickerView = new UIPickerView();
pickerView.BackgroundColor = UIColor.LightGray;
pickerView.DataSource = pickerModel;
}
}
You can create weak and strong Obj-C style Delegates:
Strong Delegate:
Create a nested UIPickerViewDelegate class within your UIViewController class:
class PickerDelegate : UIPickerViewDelegate
{
public override void Selected(UIPickerView pickerView, nint row, nint component)
{
base.Selected(pickerView, row, component);
Console.WriteLine(row.ToString());
}
}
Create and assign the delegate to your UIPickerView:
var picker = new UIPickerView(UIScreen.MainScreen.Bounds);
picker.DataSource = this;
picker.Delegate = new PickerDelegate();
Weak Delegate:
Skip the nested class and add the UIPicker selected method to your UIViewController and tag it with a Foundation.Export:
[Export("pickerView:didSelectRow:inComponent:")]
public void Selected(UIPickerView pickerView, nint row, nint component)
{
Console.WriteLine(row.ToString());
}
Assign your UIViewController as the weak delegate:
var picker = new UIPickerView(UIScreen.MainScreen.Bounds);
picker.DataSource = this;
picker.WeakDelegate = this;
Add(picker);

Pushing a DialogViewController onto a ViewController onto NavigationController stack gives 2 pages

Noob Xamarin/MonoTouch.Dialog question: I have laid out my iOS app in the storyboard designer of Xamarin Studio. I have a UINavigationController with a root view containing a UITableView with static cells, essentially creating a main menu. The cells segue to their respective UIViewControllers.
I want to layout the about/settings screen using MonoTouch.Dialog. However, I am running into some issues combining the overall storyboard approach with the partial MonoTouch.Dialogue approach due to my newbie-ness in Xamarin/MonoTouch.Dialog
When I instantiate a new DialogViewController on the UIViewController that got segued to from the initial UITableView (AccountViewController), I get essentially two views added to the navigation stack, the first only appearing briefly and then showing the DialogViewController. My code instantiating the DialogViewController is this:
partial class AccountViewController : UIViewController
{
public AccountViewController (IntPtr handle) : base (handle)
{
}
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
var root = new RootElement ("Settings") {
new Section (){
new BooleanElement ("Airplane Mode", false),
new RootElement ("Notifications", 0, 0) {
new Section (null,
"Turn off Notifications to disable Sounds\n" +
"Alerts and Home Screen Badges for the\napplications below."){
new BooleanElement ("Notifications", false)
}
}}
};
var dialog = new DialogViewController (root, true);
this.NavigationController.PushViewController (dialog, true);
//this.NavigationController.PresentViewController (dialog, true, null); tried this but then the UINavigationController shows no back buttons
//View.AddSubview (dialog.View); tried this but then the UINavigationController shows no back buttons
}
}
I'm probably pushing the DialogViewController to late in the stack, creating the intermediary blank screen, but I can't figure out where the right place is to push the DialogViewController into the navigation stack given my current architecture.
Most samples in the interwebs are nearly 100% MonoTouch.Dialog, no storyboard...
Thanks!
You're trying to push another ViewController (in this case a DialogViewController) onto the Navigation Stack while your current ViewController is still trying to load. Another words, doing that in your ViewDidLoad is bad. You're going to have to wait until your current ViewController has finished loading and has gained focus before you can push another view controller onto the stack.
Part of using Storyboards involves the navigation built into it. Am I safe to assume your "AccountViewController" really doesn't do anything? In that case, I would not segue into that. Instead on your previous view controller, just create your DialogViewController, and then manually push it onto the stack. Hard to say without looking at your storyboard and architecture.
I fixed it in the following way:
I created a custom class for my TableViewController (containing a TableView with static cells):
partial class MainMenuTableViewController : UITableViewController
{
public MainMenuTableViewController (IntPtr handle) : base (handle)
{
}
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
this.TableView.Delegate = new MainMenuTableViewDelegate (this); //this is the important part. Here I set a custom delegate class for the TableView. I pass the current TableViewController as a parameter in the constructor so I can call the NavigationController from the delegate class to push my custom MonoTouch DialogViewController onto the navigation stack
}
}
Here is the code for the TableViewDelegate:
public class MainMenuTableViewDelegate : UITableViewDelegate
{
private UITableViewController _parentController;
public MainMenuTableViewDelegate(UITableViewController parentController) : base()
{
_parentController = parentController;
}
public override void RowSelected (UITableView tableView, NSIndexPath indexPath)
{
if (indexPath.Row == 2) {
_parentController.NavigationController.PushViewController (new AccountDialogViewController(), true);
}
}
}
I override the RowSelected method in the tableview delegate class and check if the currently selected row equals index 2, the index of the TableViewCell I want to have show my MonoTouch DialogViewController (called AccountDialogViewController). If true, I push a new instance of my AccountDialogViewController onto the navigation stack via the NavigationController property of the parent TableViewController passed in through the constructor.
Here is my AccountDialogViewController:
public class AccountDialogViewController : DialogViewController
{
public AccountDialogViewController () : base(new RootElement("Account settings"), true)
{
}
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
var btnUpdatePassword = UIButton.FromType(UIButtonType.RoundedRect);
btnUpdatePassword.SetTitle("Save new password", UIControlState.Normal);
btnUpdatePassword.Frame = new RectangleF(0, 0, 320, 44);
btnUpdatePassword.TouchUpInside += delegate(object sender, EventArgs e) {
var alert = new UIAlertView("Test", "msg", null, "Cancel", null);
alert.Show();
};
Root.Add(new Section ("General") {
new EntryElement("Username", "type...", "Test"),
new EntryElement("E-mail", "type...", "Test"),
new RootElement ("Change password") {
new Section (null, btnUpdatePassword) {
new EntryElement("New password", null, null, true),
new EntryElement("Confirm", null, null, true)
}
},
new StringElement ("Logout", delegate {
var alert = new UIAlertView("Are you sure?", "Tapping Yes will log you out of your account", null, "Cancel", "Yes");
alert.Show();
})
});
}
}
So, there it is. No more weird blank screens :-)

Unable to load ViewController from tableview RowSelected in xamarin

On selected tableview rowselected loading a DetailViewcontroller class.
public override void RowSelected (UITableView tableView, NSIndexPath indexPath)
{
if (OnRowSelected != null) {
OnRowSelected (this, new RowSelectedEventArgs (tableView, indexPath));
}
var detailController = new DetailViewController ();
UINavigationController controller = new UINavigationController();
controller.PushViewController(detailController, true);
}
Unable to load the DetailViewController.
public override void RowSelected (UITableView tableView, NSIndexPath indexPath)
method is in UITableViewSource
Is there any way to load DetailViewController on rowSelected.
When you create your table, you need to place it within the context of a Navigation controller.
UINavigationController nav = new UINavigationController(myTableViewController);
Then, when you want to display your DetailViewController, you can push it onto the already existing Navigation controller. However, by default your TableSource does not have access to NavigationController - you will need to pass a reference to your TableView controller when you create the TableSource so that the TableSource can access the NavigationController:
// in your controller, when you assign the source
this.TableView.Source = new MyTableViewSource(this);
// in your source, keep a class level ref to the parent
MyTableViewController _parent;
// your Source's constructor
public MyTableViewSource(MyTableViewController parent) {
_parent = parent;
}
// finally, in your RowSelected use the _parent reference to access the Nav controller
var detailController = new DetailViewController ();
_parent.NavigationController.PushViewController(detailController, true);

Categories

Resources