MonoTouch Message Element opes page with string elements - xamarin.ios

I have the following code:
Section _section = new Section ("Test");
foreach (ExampleData data in Example.data) {
MessageElement Item = new MessageElement (){
Sender = data.Name,
Subject = data.Value,
Body = data.Description,
Date = data.Modified
} ;
_section.Add(Item);
var root = new RootElement("Item Expanded"){
new Section ("test2"){
new StringElement("Field Name", data.FieldName),
new StringElement("Value", data.Value),
new StringElement("Description", data.Description)
}
} ;
_section.Add(root);
} ;
var _rootElement = new RootElement ("Items") {
_section
} ;
I would like this to work in such a way that when a Message Element is tapped it shows the section with ("test2") that has the same data (e.g. the data was added during the same run of the loop.) I realize this will not happen currently, as it seems the Message Element
requires an Action delegate to do anything on a tap event, plus I'm adding everything to the same section. However, is there any way to replicate the behavior of multiple nested root elements and sections with a Message Element? If I create new pages/screens and try to transition that way, it rests the navigation controller and I lose the use of the back button, even if "push" is set to true.

Not sure what you want exactly. Replace your "Item Expanded" root element code with this to push a dialog viewcontoller on the navigation stack with a backbutton. Ofcourse your DialogViewcontroller should be in a UINavigation controller in the first place for this to work
Item.Tapped += delegate(DialogViewController arg1, UITableView arg2, NSIndexPath arg3)
{
var newDialogVC = new DialogViewController(
UITableViewStyle.Grouped,
new RootElement("Item Expanded")
{
new Section ("test2"){
new StringElement("Field Name", "test"),
new StringElement("Value", "test"),
new StringElement("Description", "test")
}
}
, true);
arg1.NavigationController.PushViewController(newDialogVC,true);
};

Related

JavaFX2 TreeView menu create

I have a Treeview with menu content, which is working. I am just not sure how can I implement more root menu to add?
Because this code only shows the "File" menu and all of submenus, but not the other roots.
-Also I would like to ask how could I make these submenus to act like links and create mouselisteners to them? Where is the right place to take the listeners?
The code is the following:
TreeItem<String> treeItemRoot1 = new TreeItem<> ("File");
TreeItem<String> treeItemRoot2 = new TreeItem<> ("Edit");
TreeItem<String> treeItemRoot3 = new TreeItem<> ("View");
TreeItem<String> treeItemRoot4 = new TreeItem<> ("Tools");
TreeItem<String> treeItemRoot5 = new TreeItem<> ("Help");
TreeItem<String> nodeItemA = new TreeItem<>("Item A");
TreeItem<String> nodeItemB = new TreeItem<>("Item B");
TreeItem<String> nodeItemC = new TreeItem<>("Item C");
treeItemRoot1.getChildren().addAll(nodeItemA, nodeItemB, nodeItemC);
TreeView<String> treeView = new TreeView<>(treeItemRoot1);
StackPane.getChildren().add(treeView);
The first part of your question is answered here: Set two root nodes for TreeView
For the second part, it depends on exactly what functionality you want. If you want to respond to a change in the selected item in the tree (this would include the user selecting either with the mouse or by using the keyboard), so can add a listener to the tree's selected item:
treeView.getSelectionModel().selectedItemProperty().addListener((obs, oldItem, newItem) -> {
if (newItem == treeItemRoot1) {
// "file" selected...
} else if (newItem == treeItemRoot2) {
// edit selected
} // etc...
});
If you genuinely want a mouse listener, you need to add a listener to the cell. To do this, use a cell factory:
treeView.setCellFactory(tv -> {
TreeCell<String> cell = new TreeCell<>();
cell.textProperty().bind(cell.itemProperty());
cell.setOnMousePressed(event -> {
TreeItem<String> item = cell.getTreeItem();
if (item == treeItemRoot1) {
// "file" clicked...
} else if (item == treeItemRoot2) {
// etc...
}
}
return cell ;
});
You can probably find ways to organize the code a little more cleanly, and avoid the big if-else construct in either case.

Determine which Monotouch.Dialog Checkbox was checked/unchecked

I have a list of people that I want to display with checkboxes next to their names. When an CheckBoxElement (person) is checked or unchecked, I need to handle the event.
List<CheckboxElement> cbPersonElements = new List<CheckboxElement> ();
CheckboxElement tmpCheckbox = new CheckboxElement ("");
foreach (ABPerson itemPerson in _people) {
tmpCheckbox = new CheckboxElement (itemPerson.LastName);
cbPersonElements.Add(tmpCheckbox);
}
And then I add the list when I create the RootElement:
RootElement _rootElement = new RootElement ("People List"){
new Section ("People"){
cbPersonElements
}
How should I add a handler that will allow me to detected which CheckBoxElement was clicked.
I can't attach one to tmpCheckbox, that value changes with each iteration through the loop.
Seems like it should be simple, but I can't see it.
Thanks.
you should be able to use a ValueChanged handler
foreach (ABPerson itemPerson in _people) {
tmpCheckbox = new CheckboxElement (itemPerson.LastName);
tmpCheckbox.ValueChanged += delegate {
// do something here based on tmpCheckbox.Value
};
cbPersonElements.Add(tmpCheckbox);
}

Monotouch.Dialog StyledStringElement delegate always fires for the last element added

given the following code, I am having an issue when clicking on each element. If we assume I have 5 exercises and therefore create 5 elements in the foreach() loop, when the table is rendered and I click on any element, the delegate always gets the exercise of the 5th (last) element.
The elements are displayed properly, each showing the associated exercise's name. It is just the delegate that does not work as expected.
If I do not use a foreach loop and hardcode each element instead it works as expected. However if I cannot dynamically populate the dialogViewController and use the element tapped event for each one, is not good.
private void CreateExerciseTable()
{
Section section = new Section();
foreach (var exercise in exercises)
{
var element = new StyledStringElement(exercise.ExerciseName,
delegate { AddExercise(exercise); })
{
Font = Fonts.H3,
TextColor = UIColor.White,
BackgroundColor = RGBColors.LightBlue,
Accessory = UITableViewCellAccessory.DisclosureIndicator
};
section.Elements.Add(element);
}
var root = new RootElement("Selection") {
section
};
var dv = new DialogViewController(root, true);
dv.Style = UITableViewStyle.Plain;
//Remove the extra blank table lines from the bottom of the table.
UIView footer = new UIView(new System.Drawing.RectangleF(0,0,0,0));
dv.TableView.TableFooterView = footer;
dv.TableView.SeparatorColor = UIColor.White;
dv.TableView.BackgroundColor = UIColor.White;
tableFitnessExercises.AddSubview(dv.View);
}
private void AddExercise(FitnessExercise exercise)
{
NavigationManager.FitnessRoutine.Add(exercise);
PerformSegue(UIIdentifierConstants.SegAddExerciseToFitnessRoutine, this);
}
This is a classic closure bug!
The problem is that you are accessing the loop reference.
Try:
foreach (var exercise in exercises)
{
var localRef = exercise;
var element = new StyledStringElement(exercise.ExerciseName,
delegate { AddExercise(localRef); })
{
Font = Fonts.H3,
TextColor = UIColor.White,
BackgroundColor = RGBColors.LightBlue,
Accessory = UITableViewCellAccessory.DisclosureIndicator
};
section.Elements.Add(element);
}
For more on this see http://blogs.msdn.com/b/ericlippert/archive/2009/11/12/closing-over-the-loop-variable-considered-harmful.aspx

Why is UILabel not updating?

I have created a view that shows lost connection messages to users which pops over the current view. I want to update the view periodically based on connection status changes.
I can properly get the view and change the text of a label (verified with WriteLines), but nothing changes on the actual display. I even tried removing the view and readding it and calling SetNeedsDisplay, but nothing seems to help.
I have a global variable called OverView:
public static UIView OverView;
I create the label subview, add it to the overview and pop the overview in front of the current view:
UILabel labelTitle = new UILabel();
labelTitle.Text = title;
UIView labelTitleView = (UIView) labelTitle;
labelTitleView.Tag = 5000;
OverView.AddSubview(labelTitleView);
curView.InsertSubviewAbove(OverView, curView);
curView.BringSubviewToFront(OverView);
And then at a later time, I try to modify it like this from another function:
if ((OverView != null) && (OverView.Subviews != null))
{
for (int i = 0; i < OverView.Subviews.Length; i++)
{
WriteToConsole("Type: " + OverView.Subviews[i].GetType());
if (OverView.Subviews[i] is UILabel)
{
WriteToConsole("Found Label with Tag: " + ((UILabel)(OverView.Subviews[i])).Tag + " Text: " + ((UILabel)(OverView.Subviews[i])).Text);
if (((UILabel)(OverView.Subviews[i])).Tag == 5000)
{
WriteToConsole("Setting subview Title to: " + lostConnectionTitle);
lock (overViewLocker)
{
appReference.InvokeOnMainThread(delegate
{
UILabel tempLabel = ((UILabel)(OverView.Subviews[i]));
tempLabel.Text = lostConnectionTitle;
OverView.Subviews[i].RemoveFromSuperview();
OverView.AddSubview(tempLabel);
OverView.BringSubviewToFront(tempLabel);
OverView.SetNeedsLayout();
OverView.SetNeedsDisplay();
WriteToConsole("SetNeedsDisplay");
});
}
}
}
}
}
Have you tried to use delegate methods on your label, and change their value when events occur ?
For example, if your event is clicking on a button, you should have something like that:
yourLabel.Text = "Init";
buttonExample.TouchUpInside += (sender, e) => {
yourLabel.Text = "I touched my button";
};
When your View loads, you'll see "Init" and your button and once you click on it, the label text changed.
Xamarin has some explanation about events and delegate methods here.
I hope that helped.

MonoTouch Dialog elements are not updating/repainting themselves

I have the following in a Section:
_favElement = new StyledStringElement (string.Empty);
_favElement.Alignment = UITextAlignment.Center;
if (_room.IsFavourite) {
_favElement.Image = UIImage.FromBundle ("Images/thumbs_up.png");
_favElement.Caption = "Unmark as Favourite";
} else {
_favElement.Image = null;
_favElement.Caption = "Mark as Favourite";
}
_favElement.Tapped += favElement_Tapped;
Then when I press the element I want the following to happen:
private void favElement_Tapped ()
{
if (_room.IsFavourite) {
_favElement.Image = null;
_favElement.Caption = "Mark as Favourite";
} else {
_favElement.Image = UIImage.FromBundle ("Images/thumbs_up.png");
_favElement.Caption = "Unmark as Favourite";
}
_room.IsFavourite = !_room.IsFavourite;
}
However the image and text does not change in the actual element when the element is tapped. Is there a refresh method or something that must be called? I've also tried changing the Accessory on Tapped as well and nothing changes. The properties behind do reflect the correct values though.
An alternative to reloading the UITableView is to reload the Element using code like this (copied from Touch.Unit):
if (GetContainerTableView () != null) {
var root = GetImmediateRootElement ();
root.Reload (this, UITableViewRowAnimation.Fade);
}
assuming that your code is in DialogViewController,add this
this.ReloadData();
but in your case I recommend you to use BooleanImageElement

Resources