Billy Coover
Billy Coover

Reputation: 3837

MonoTouch.Dialog : Advanced Editing

I'm trying to put together a detail view that is editable, similar to the iPhone default contacts app.

I have a TableView of contacts and I activate an editable detail view when a cell is selected:

public override void Selected (DialogViewController dvc, UITableView tableView, NSIndexPath path)
{       
    var editingSection = new Section ("Entity") {
        new StringElement ("First name", "enter", _entity.FirstName),
        new StringElement ("Last name", "enter", _entity.LastName)
    };

    var root = new RootElement("Entity Entry") {
        editingSection
    };

    var entityEdit = new EntityEdit (root, true);
    ConfigEdit (entityEdit);            
    dvc.ActivateController(entityEdit);

}

void ConfigEdit (DialogViewController dvc)
{
    dvc.NavigationItem.RightBarButtonItem = new UIBarButtonItem (UIBarButtonSystemItem.Edit, delegate {
        dvc.TableView.SetEditing (true, true);
        ConfigDone (dvc);
    });
}

void ConfigDone (DialogViewController dvc)
{
    dvc.NavigationItem.RightBarButtonItem = new UIBarButtonItem (UIBarButtonSystemItem.Done, delegate {
        dvc.TableView.SetEditing (false, true);
        ConfigEdit (dvc);
    });
}

The behavior that I want to change is in the ConfigEdit method. When I first show the view, the elements in the editing section should be StringElements. When I switch to edit mode, the elements should change to entry Elements because I want the ability to delete the row, or edit the text inside the element.

Is this possible? Is there a better approach to showing read-only elements until edit mode has been set?

Upvotes: 3

Views: 3658

Answers (2)

Billy Coover
Billy Coover

Reputation: 3837

Based on Miguel's answer, here is what I did:

public partial class AppDelegate
{       
    public void DemoAdvancedEditing () 
    {
        var root = new RootElement ("Todo list") {
            new Section() {
                new StringElement ("1", "Todo item 1"),
                new StringElement ("2","Todo item 2"),
                new StringElement ("3","Todo item 3"),
                new StringElement ("4","Todo item 4"),
                new StringElement ("5","Todo item 5")
            }
        };
        var dvc = new AdvancedEditingDialog (root, true);
        AdvancedConfigEdit (dvc);           
        navigation.PushViewController (dvc, true);
    }

    void AdvancedConfigEdit (DialogViewController dvc)
    {
        dvc.NavigationItem.RightBarButtonItem = new UIBarButtonItem (UIBarButtonSystemItem.Edit, delegate {
            // Activate editing
            // Switch the root to editable elements     
            dvc.Root = CreateEditableRoot(dvc.Root, true);
            dvc.ReloadData();   
            // Activate row editing & deleting
            dvc.TableView.SetEditing (true, true);
            AdvancedConfigDone(dvc);                
        });
    }

    void AdvancedConfigDone (DialogViewController dvc)
    {
        dvc.NavigationItem.RightBarButtonItem = new UIBarButtonItem (UIBarButtonSystemItem.Done, delegate {
            // Deactivate editing
            dvc.ReloadData();
            // Switch updated entry elements to StringElements
            dvc.Root = CreateEditableRoot(dvc.Root, false);
            dvc.TableView.SetEditing (false, true);
            AdvancedConfigEdit (dvc);
        });
    }

    RootElement CreateEditableRoot (RootElement root, bool editable)
    {
        var rootElement = new RootElement("Todo list") {
            new Section()
        };

        foreach (var element in root[0].Elements) {
            if(element is StringElement) {
                rootElement[0].Add(CreateEditableElement (element.Caption, (element as StringElement).Value, editable));
            } else {
                rootElement[0].Add(CreateEditableElement (element.Caption, (element as EntryElement).Value, editable));
            }
        }

        return rootElement;
    }

    Element CreateEditableElement (string caption, string content, bool editable)
    {
        if (editable) {
            return new EntryElement(caption, "todo", content);
        } else {
            return new StringElement(caption, content);
        }
    }
}

Upvotes: 0

miguel.de.icaza
miguel.de.icaza

Reputation: 32694

You have a couple of options:

a. You can just change the RootElement with an updated RootElement, or update the individual cells with new cells of the proper type of element to get the desired effect. You could do this by parametrizing your creation:

RootElement CreateRoot (bool editable)
{
    return new RootElement (...) {
         CreateEditableElement ("foo", bar, editable)
    }
}

Element CreateEditableElement (string caption, string content, bool editable)
{
     return editable ? EntryElement (caption, content) : StringELement (caption, content)
}

Then you need to call ReloadData after the user has tapped the "Edit" button.

The other thing that you could do is to create a new Element that can switch states based on this information. My blog has a tutorial on how to create new elements:

http://tirania.org/monomac/archive/2011/Jan-18.html

Upvotes: 6

Related Questions