0
votes

I am using MonoTouch.Dialog to create a page in my Xamarin iOS app.

I am trying to create a multi-line RootElement by leveraging the GetCell method. This works fine on load, but if you click to a different tab and back the element shrinks back to default size (also when you click the element you see it shrink before the transition).

I have tried messing with UnevenRows with no success so far.

public partial class TestController : UITabBarController
{
    public TestController()
        : base("TestController", null)
    {
    }

    public override void ViewDidLoad()
    {
        base.ViewDidLoad();

        var navController = new UINavigationController
        {
            Title = "Test1"
        };
        navController.PushViewController(new TestDialogViewController(), false);

        ViewControllers = new[]
        {
            navController, 
            new UIViewController
            {
                Title = "Test2"
            },
        };
    }
}

public class TestDialogViewController : DialogViewController
{
    public TestDialogViewController() : base(new RootElement("Test"))
    {
        Root.UnevenRows = true; // has no effect

        var testSection = new Section("Test section");
        var testChildRootElement = new CustomRootElement("Multi\nLine\nElement")
        {
            UnevenRows = true // has no effect
        };

        var testChildSection = new Section("Test child section");
        var testEntryElement = new EntryElement(string.Empty, string.Empty, "Test entry element");

        testChildSection.Add(testEntryElement);
        testChildRootElement.Add(testChildSection);
        testSection.Add(testChildRootElement);

        Root.Add(testSection);
    }
}

public class CustomRootElement : RootElement
{
    public CustomRootElement(string caption) : base(caption) {}

    public override UITableViewCell GetCell(UITableView tv)
    {
        var cell = base.GetCell(tv);

        // Setup Multi-line Element
        cell.TextLabel.LineBreakMode = UILineBreakMode.WordWrap;
        cell.TextLabel.Lines = 0;
        return cell;
    }
}
1

1 Answers

1
votes

Found a workaround that seems to do the trick

Add this to the DialogViewController:

public override void ViewWillLayoutSubviews()
    {
        if (TableView != null && TableView.VisibleCells.Any())
        {
            foreach (var cell in TableView.VisibleCells)
            {
                cell.SizeToFit();
            }
        }
        base.ViewWillLayoutSubviews();
    }

UPDATED:

The above solution did not work with multiple elements, as the heights were not being calculated when the table was drawn.

A better solution was to use a custom UITableViewSource (inherit from the MonoTouch.Dialog.DialogViewController.SizingSource which is used by default has all the extra functionality).

Below is a basic implementation for clarity, but you probably won't want to be calling GetCell() every time GetHeight() is called in a production version.

public partial class TestController : UITabBarController
{
    public TestController() : base("TestController", null) {}

    public override void ViewDidLoad()
    {
        base.ViewDidLoad();

        var navController = new UINavigationController();
        navController.PushViewController(new TestDialogViewController(), false);
        navController.TopViewController.Title = "Tab 1";

        ViewControllers = new[]
        {
            navController, 
            new UIViewController { Title = "Test2" }
        };
    }
}

public class TestDialogViewController : DialogViewController
{
    public TestDialogViewController() : base(new RootElement("Test"))
    {
        Root.Add(new Section("Test section")
        {
            new CustomRootElement("Multi\nLine\nElement")
            {
                new Section("Test child section")
                {
                    new EntryElement("Test element", string.Empty, "value")
                },
            },
            new EntryElement("Test element", string.Empty, "value")
        });
    }

    public override void ViewDidLoad()
    {
        base.ViewDidLoad();
        TableView.Source = new CustomTableViewSource(this);
    }

}

public class CustomTableViewSource : DialogViewController.SizingSource
{
    public CustomTableViewSource(DialogViewController controller) : base(controller) {}

    public override float GetHeightForRow(UITableView tableView, NSIndexPath indexPath)
    {
        // Recommend storing these values, as is appropriate for your usage
        var cell = GetCell(tableView, indexPath);
        cell.SizeToFit();
        return cell.Frame.Height;
    }
}


public class CustomRootElement : RootElement
{
    public CustomRootElement(string caption) : base(caption) {}

    public override UITableViewCell GetCell(UITableView tv)
    {
        var cell = base.GetCell(tv);

        // Setup Multi-line Element
        cell.TextLabel.LineBreakMode = UILineBreakMode.WordWrap;
        cell.TextLabel.Lines = 0;

        return cell;
    }
}