Connect marker with EditPart - resources

I have a graphical editor which extends GraphicalEditorWithFlyoutPalette.
There could be appear different markers, so it would be nice, if there is any possibility to connect the marker with the EditPart.
I think one possibility is to extend the TableViewer and the corresponding cell classes. But perhaps there is a better and more easier way.
I create my test markers like following:
IResource resource = (IResource) input.getAdapter(IResource.class);
try
{
IMarker marker = resource.createMarker(IMarker.PROBLEM);
marker.setAttribute(IMarker.TEXT, "text");
marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR);
marker.setAttribute(IMarker.MESSAGE, "message");
}
catch (CoreException e)
{
e.printStackTrace();
}
input is my IEditorInput.

In my first attempt, I was trying to extends the ExtendedMarkersView, which fails because it is an internal class.
Another way was to write the view and all corresponding stuff new, but it seems to be senseless.
So I found a work around based on https://stackoverflow.com/a/10501971/390177.
While creating the IMarker, I set additional attributes to link the corresponding data object. With the help of the object I can search for the AbstractGraphicalEditPart with the EditPartRegistry.
After that it is possible to create a selection on the EditPart and reveal to it.
#Override
public void selectionChanged(IWorkbenchPart part, ISelection selection) {
IStructuredSelection s = (IStructuredSelection) selection;
if (s.getFirstElement() instanceof MarkerItem) {
MarkerItem marker = (MarkerItem) s.getFirstElement();
if (marker != null && marker.getMarker() != null) {
IMarker iMarker = marker.getMarker();
AbstractGraphicalEditPart editPart = null;
DataObject object ...
editPart = (AbstractGraphicalEditPart) getGraphicalViewer().getEditPartRegistry().get(object);
if (editPart != null) {
StructuredSelection eSelection = new StructuredSelection(editPart);
getGraphicalViewer().setSelection(eSelection);
// once selected if you want to get it so the
// graphicalviewer scrolls to reveal the part on the
// screen
getGraphicalViewer().reveal(editPart);
}
}
} else {
super.selectionChanged(part, selection);
}
}

Related

lotus.domino.local.Item cannot be cast to lotus.domino.RichTextItem

I try to put a file into a richtext but it crashes !
In my first code, I try to use directly "getFirstItem", in first time it was ok but now i try to use it again and it crashed.
In second time i pass with an object and it find my obj doesn't an richtextItem (instanceof) ???
I don't understand.
I have the message : "lotus.domino.local.Item cannot be cast to lotus.domino.RichTextItem" ?
Could you help me ?
public void copieFichierDansRichText(String idDocument, String nomRti, File file,
String nameFichier, String chemin) throws NotesException {
lotus.domino.Session session = Utils.getSession();
lotus.domino.Database db = session.getCurrentDatabase();
lotus.domino.Document monDoc = db.getDocumentByUNID(idDocument);
lotus.domino.RichTextItem rtiNew = null;
try {
try {
if (monDoc != null) {
// if (monDoc.getFirstItem(nomRti) != null) {
// rtiNew = (lotus.domino.RichTextItem)
// monDoc.getFirstItem(nomRti);
// } else {
// rtiNew = (lotus.domino.RichTextItem)
// monDoc.createRichTextItem(nomRti);
// }
Object obj = null;
if (monDoc.getFirstItem(nomRti) != null) {
obj = monDoc.getFirstItem(nomRti);
if (obj instanceof lotus.domino.RichTextItem) {
rtiNew = (lotus.domino.RichTextItem) obj;
}
} else {
obj = monDoc.createRichTextItem(nomRti);
if (obj instanceof lotus.domino.RichTextItem) {
rtiNew = (lotus.domino.RichTextItem) obj;
}
}
PieceJointe pieceJointe = new PieceJointe();
pieceJointe = buildPieceJointe(file, nameFichier, chemin);
rtiNew.embedObject(EmbeddedObject.EMBED_ATTACHMENT, "", pieceJointe.getChemin()
+ pieceJointe.getNomPiece(), pieceJointe.getNomPiece());
monDoc.computeWithForm(true, false);
monDoc.save(true);
}
} finally {
rtiNew.recycle();
monDoc.recycle();
db.recycle();
session.recycle();
}
} catch (Exception e) {
e.printStackTrace();
}
}
EDIT : I try to modify my code with yours advices but the items never considerate as richtextitem. It is my problem. I don't understand why, because in my field it is a richtext ! For it, the item can't do :
rtiNew = (lotus.domino.RichTextItem) item1;
because item1 not be a richtext !!!
I was trying to take all the fields and pass in the item one by one, and it never go to the obj instance of lotus.domini.RichTextItem....
Vector items = doc.getItems();
for (int i=0; i<items.size(); i++) {
// get next element from the Vector (returns java.lang.Object)
Object obj = items.elementAt(i);
// is the item a RichTextItem?
if (obj instanceof RichTextItem) {
// yes it is - cast it as such // it never go here !!
rt = (RichTextItem)obj;
} else {
// nope - cast it as an Item
item = (Item)obj;
}
}
A couple of things. First of all I would set up a util class method to handle the object recycling in a neater way:
public enum DominoUtil {
;
public static void recycle(Base... bases) {
for (Base base : bases) {
if (base != null) {
try {
base.recycle();
} catch (Exception e) {
// Do nothing
}
}
}
}
}
Secondly I would remove the reduntants try/catch blocks and simplify it like this:
private void copieFichierDansRichText(String idDocument, String nomRti, File file,
String nameFichier, String chemin) {
Session session = DominoUtils.getCurrentSession();
Database db = session.getCurrentDatabase();
Document monDoc = null;
try {
monDoc = db.getDocumentByUNID(idDocument);
Item item = monDoc.getFirstItem(nomRti);
if (item == null) {
item = monDoc.createRichTextItem(nomRti);
} else if (item.getType() != Item.RICHTEXT) {
// The item is not a rich text item
// What are you going to do now?
}
RichTextItem rtItem = (RichTextItem) item;
PieceJointe pieceJointe = new PieceJointe();
pieceJointe = buildPieceJointe(file, nameFichier, chemin);
rtItem.embedObject(EmbeddedObject.EMBED_ATTACHMENT, "", pieceJointe.getChemin()
+ pieceJointe.getNomPiece(), pieceJointe.getNomPiece());
monDoc.computeWithForm(true, false);
monDoc.save(true);
} catch (NotesException e) {
throw new FacesException(e);
} finally {
DominoUtil.recycle(monDoc);
}
}
Finally, apart from the monDoc, you need not recycle anything else. Actually Session would be automatically recycled and anything beneath with it (so no need to recycle db, let alone the session!, good rule is don't recycle what you didn't instantiate), but it's not bad to keep the habit of keeping an eye on what you instantiate. If it were a loop with many documents you definitively want to do that. If you also worked with many items you would want to recycle them as early as possible. Anyway, considered the scope of the code it's sufficient like this. Obviously you would call DominoUtil.recycle directly from the try block. If you have multiple objects you can recycle them at once possibly by listing them in the reverse order you set them (eg. DominoUtil.recycle(item, doc, view)).
Also, what I think you miss is the check on the item in case it's not a RichTextItem - and therefore can't be cast. I put a comment where I think you should decide what to do before proceeding. If you let it like that and let the code proceed you will have the code throw an error. Always better to catch the lower level exception and re-throw a higher one (you don't want the end user to know more than it is necessary to know). In this case I went for the simplest thing: wrapped NotesException in a FacesException.

Unity Vuforia Google VR - Can't make onPointerEnter to GameObject change material for itself

I have two 3d buttons in my scene and when I gaze into any of the buttons it will invoke OnPointerEnter callback and saving the object the pointer gazed to.
Upon pressing Fire1 on the Gamepad I apply materials taken from Resources folder.
My problem started when I gazed into the second button, and pressing Fire1 button will awkwardly changed both buttons at the same time.
This is the script I attached to both of the buttons
using UnityEngine;
using UnityEngine.EventSystems;
using Vuforia;
using System.Collections;
public class TriggerMethods : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler
{
Material _mat;
GameObject targetObject;
Renderer rend;
int i = 0;
// Update is called once per frame
void Update () {
if (Input.GetButtonDown("Fire1"))
TukarMat();
}
public void OnPointerEnter(PointerEventData eventData)
{
targetObject = ExecuteEvents.GetEventHandler<IPointerEnterHandler>(eventData.pointerEnter);
}
public void OnPointerExit(PointerEventData eventData)
{
targetObject = null;
}
public void TukarMat()
{
Debug.Log("Value i = " + i);
if (i == 0)
{
ApplyTexture(i);
i++;
}
else if (i == 1)
{
ApplyTexture(i);
i++;
}
else if (i == 2)
{
ApplyTexture(i);
i = 0;
}
}
void ApplyTexture(int i)
{
rend = targetObject.GetComponent<Renderer>();
rend.enabled = true;
switch (i)
{
case 0:
_mat = Resources.Load("Balut", typeof(Material)) as Material;
rend.sharedMaterial = _mat;
break;
case 1:
_mat = Resources.Load("Khasiat", typeof(Material)) as Material;
rend.sharedMaterial = _mat;
break;
case 2:
_mat = Resources.Load("Alma", typeof(Material)) as Material;
rend.sharedMaterial = _mat;
break;
default:
break;
}
}
I sensed some logic error and tried making another class to only manage object the pointer gazed to but I was getting more confused.
Hope getting some helps
Thank you
TukarMat() is beeing called on both buttons when you press Fire1. If targetObject is really becoming null this should give an error on first button since it's trying to get component from a null object. Else, it'll change both as you said. Make sure OnPointerExit is beeing called.
Also, it seems you are changing the shared material.
The documentation suggests:
Modifying sharedMaterial will change the appearance of all objects using this material, and change material settings that are stored in the project too.
It is not recommended to modify materials returned by sharedMaterial. If you want to modify the material of a renderer use material instead.
So, try changing the material property instead of sharedMaterial since it'll change the material for that object only.

j2me - Filter results by two or more criteria

I'm trying to filter some records using the RecordFilter interface. In my app I have a couple of interfaces similar to this one, on which the user can enter an ID or Name (he/she could enter both or neither of them too)
Here's what I've done so far:
The Customer filter.
Here if the user didn't enter an ID, I pass 0 as a default value, that's why I evaluate customerID!=0
public class CustomerFilter implements RecordFilter {
private String mName_Filter;
private int mID_Filter;
public CustomerFilter(String name_Filter, int id_Filter) {
this.mName_Filter = name_Filter.toLowerCase();
this.mID_Filter = id_Filter;
}
public boolean matches(byte[] candidate) {
try {
ByteArrayInputStream bis = new ByteArrayInputStream(candidate);
DataInputStream dis = new DataInputStream(bis);
int customerID = dis.readInt();
String customerName = dis.readUTF().toLowerCase();
if ((customerName != null && customerName.indexOf(mName_Filter) != -1) && (customerID != 0 && customerID == mID_Filter))
return true;
if (customerName != null && customerName.indexOf(mName_Filter) != -1 && customerID == 0)
return true;
if (customerName == null && (customerID != 0 && customerID == mID_Filter))
return true;
if (customerName == null && customerID == 0)
return true;
} catch (IOException ex) {
//What's the point in catching a exception here???
}
return false;
}
}
The search method:
Note: This method is in a class that I call "RMSCustomer", in which I deal with everything related to RMS access. The search method receives two parameters (id and name) and uses them to instantiate the filter.
public Customer[] search(int id, String name) throws RecordStoreException, IOException {
RecordStore rs = null;
RecordEnumeration recEnum = null;
Customer[] customerList = null;
try {
rs = RecordStore.openRecordStore(mRecordStoreName, true);
if (rs.getNumRecords() > 0) {
CustomerFilter filter = new CustomerFilter(name, id);
try {
recEnum = rs.enumerateRecords(filter, null, false);
if (recEnum.numRecords() > 0) {
customerList = new Customer[recEnum.numRecords()];
int counter = 0;
while (recEnum.hasNextElement()) {
Customer cust;
int idRecord = recEnum.nextRecordId();
byte[] filterRecord = rs.getRecord(idRecord);
cust = parseRecord(filterRecord);
cust.idRecord = idRecord;
customerList[counter] = cust;
counter++;
}
}
else{
customerList = new Customer[0];
//How to send a message to the midlet from here
//saying something like "No Record Exists.Please select another filter"
}
} finally {
recEnum.destroy();
}
}
else{
//How to send a message to the midlet from here
//saying something like "No Record Exists.Please Add record"
}
} finally {
rs.closeRecordStore();
}
return customerList;
}
Even though, the code shown above works I still have some questions/problems:
In the Filter :
1) How can I improve the code that evaluates the possible values of the filters (name,id)? What if I had more filters?? Will I have to test all the possible combinations??
2) If the user doesn’t enter neither a ID nor a name, should I display all the records or should I display a message "Please enter a name or ID"?? What would you do in this case?
3) Why do I have to put a try-catch in the filter when I can't do anything there?? I can't show any alert from there or can I?
In the search method:
1) How can I show a proper message to the user from that method? something like "No records" (see the "ELSE" parts in my code
Sorry If I asked too many questions, it's just that there's any complete example of filters.
Thanks in advance
How can I improve the code that evaluates the possible values of the
filters (name,id)?
The ID is the first field in the record and the fastest one to search for. If the Id matches, It doesn't really matter what the customer name is. Normally you'll be looking for the records where the ID matches OR the customer name matches, so once the ID matches you can return true. This is my proposal for the CustomerFilter class:
public class CustomerFilter implements RecordFilter {
private String mName_Filter;
//Use Integer instead of int.
//This way we can use null instead of zero if the user didn't type an ID.
//This allows us to store IDs with values like 0, -1, etc.
//It is a bit less memory efficient,
//but you are not creating hundreds of filters, are you? (If you are, don't).
private Integer mID_Filter;
public CustomerFilter(String name_Filter, Integer id_Filter) {
this.mName_Filter = normalizeString(mName_Filter);
this.mID_Filter = id_Filter;
}
//You should move this function to an StringUtils class and make it public.
//Other filters might need it in the future.
private static String normalizeString(final String s){
if(s != null){
//Warning: you might want to replace accentuated chars as well.
return s.toLowerCase();
}
return null;
}
public boolean matches(byte[] candidate) {
ByteArrayInputStream bis = new ByteArrayInputStream(candidate);
DataInputStream dis = new DataInputStream(bis);
try {
if(mID_Filter != null){
//If the ID is unique, and the search is ID OR other fields, this is fine
int customerID = dis.readInt();
if(mID_Filter.intValue == customerID){
return true;
} else {
return false;
}
}
if(mName_Filter != null){
String customerName = normalizeString(dis.readUTF());
if(customerName != null && customerName.indexOf(mName_Filter) != -1){
return true;
}
}
if(mID_Filter == null && mName_Filter == null){
return true; // No filtering, every record matches.
}
} catch (IOException ex) {
//Never swallow exceptions.
//Even if you are using an underlying ByteArrayInputStream, an exception
//can still be thrown when reading from DataInputStream if you try to read
//fields that do not exists.
//But even if no exceptions were ever thrown, never swallow exceptions :)
System.err.println(ex);
//Optional: throw ex;
} finally {
//Always close streams.
if(bis != null){
try {
bis.close();
} catch(IOException ioe){
System.err.println(ioe);
}
}
if(dis != null){
try {
dis.close();
} catch(IOException ioe){
System.err.println(ioe);
}
}
}
return false;
}
}
What if I had more filters?? Will I have to test all the possible
combinations??
It depends on your project. Usually the ID is unique and no two records exist with the same id. In this case you should explicitly design the screen so that the user understands that either he types an Id, or else he fills in the other fields. The condition would be like this:
idMatches OR (field1Matches AND field2Matches AND ... fieldNMatches)
If the user types nothing, then all records will be returned.
But then again this is more a UX issue, I don't know if it is valid for your requirements.
From the programming point of view, what is clear is that the more fields you add, the more messy your filter will became. To prevent this, you could use patterns like Decorator, Composite, and even Chain of responsibility. You'll probably have to trade good design for performance though.
If the user doesn’t enter neither a ID nor a name, should I display
all the records or should I display a message "Please enter a name or
ID"?? What would you do in this case?
It depends. Is there any other way to view all records? If so, then show the message.
Why do I have to put a try-catch in the filter when I can't do
anything there?? I can't show any alert from there or can I?
You shouldn't. This class is only responsible of filtering, not of interacting with the user. You can still log the error from the catch clause, and then throw the exception again. That will propagate the exception up to RMSCustomer.search, so whatever client code is calling that function will handle the exception in the same way you are handling the other ones thrown by that method. But keep the finally clause to close the streams.
How can I show a proper message to the user from that method?
something like "No records" (see the "ELSE" parts in my code)
You shouldn't do anything related to the GUI (like showing dialogs) from the RMSCustomer class. Even if you are not using the Model-View-Controller pattern, you still want to keep your class focused on a single responsibility (managing records). This is called the Single responsibility principle.
Keeping your class isolated from the GUI will allow you to test it and reuse it in environments without GUI.
The no records case should be handled by the screen when there are zero results. An array of lenght == 0 is fine here, and the screen will show the "No results" message. For other kinds of errors, you can extend the Exception class and throw your own custom exceptions, i.e: RecordParsingException, from the RMSCustomer.search method. The screen class will then map the different exceptions to the error message in the language of the user.

How to stop onItemSelected() from firing off multiple times after a selection of an item was made?

I've seen another similar thread, but I wasn't able to resolve my issue with the given answers.
EXPLANATION OF MY GOALS:
I have 4 spinners, each has its own ArrayList of strings assigned to it via an adapter. All of these arrays contain the same values at the beginning.
I want to remove the selected value (eg. "item" in spinner1) from all the other spinners (remove "item" from spinner2, 3 and 4) when it is selected.
PROBLEM:
When I select an item for the first two or three times from different spinners (the number of selections needed to reproduce the problem varies) the onItemSelected() method gets called multiple times (the number of callings is greater than the number of actual -user- selections made).
QUESTION:
How to prevent the calling of onItemSelected(); at unnecessary times. I want it to be called only when the actual user makes a selection in one of the spinners and only call it once when that does happen.
If you want to try to help me out and you need more code / images of the problem on the device itself, please, say so.
Here is my whole onItemSelected() method:
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
if (inCorrection == false)
{
s1 = spinner1.getSelectedItemPosition();
s2 = spinner2.getSelectedItemPosition();
s3 = spinner3.getSelectedItemPosition();
s4 = spinner4.getSelectedItemPosition();
testcount++;
switch(parent.getId())
{
case R.id.v1_q1_s1:
if((position != AdapterView.INVALID_POSITION) && (spinner1.getSelectedItem().toString() != "Default---"))
{
findLists(myList2, myList3, myList4, spinner1.getSelectedItem().toString());
if(returnChecks(0) != "Default---")
{
myList2.add(returnChecks(0));
myList3.add(returnChecks(0));
myList4.add(returnChecks(0));
}
addChecks(0, (spinner1.getSelectedItem().toString()));
}
else
{
if(position != AdapterView.INVALID_POSITION)
{
myList2.add(returnChecks(0));
myList3.add(returnChecks(0));
myList4.add(returnChecks(0));
addChecks(0, (spinner1.getSelectedItem().toString()));
}
}
adapter1.notifyDataSetChanged();
adapter2.notifyDataSetChanged();
adapter3.notifyDataSetChanged();
adapter4.notifyDataSetChanged();
Toast.makeText(Vprasalnik1.this, myList1.toString()+"\n"+myList2.toString()+"\n"+myList3.toString()+"\n"+myList4.toString()+"\n"+checks.toString(), Toast.LENGTH_LONG).show();
break;
case R.id.v1_q1_s2:
if((position != AdapterView.INVALID_POSITION) && (spinner2.getSelectedItem().toString() != "Default---"))
{
findLists(myList1, myList3, myList4, spinner2.getSelectedItem().toString());
if(returnChecks(1) != "Default---")
{
myList1.add(returnChecks(1));
myList3.add(returnChecks(1));
myList4.add(returnChecks(1));
}
addChecks(1, (spinner2.getSelectedItem().toString()));
}
else
{
if(position != AdapterView.INVALID_POSITION)
{
myList1.add(returnChecks(1));
myList3.add(returnChecks(1));
myList4.add(returnChecks(1));
addChecks(1, (spinner2.getSelectedItem().toString()));
}
}
adapter1.notifyDataSetChanged();
adapter2.notifyDataSetChanged();
adapter3.notifyDataSetChanged();
adapter4.notifyDataSetChanged();
Toast.makeText(Vprasalnik1.this, myList1.toString()+"\n"+myList2.toString()+"\n"+myList3.toString()+"\n"+myList4.toString()+"\n"+checks.toString(), Toast.LENGTH_LONG).show();
break;
case R.id.v1_q1_s3:
if((position != AdapterView.INVALID_POSITION) && (spinner3.getSelectedItem().toString() != "Default---"))
{
findLists(myList2, myList1, myList4, spinner3.getSelectedItem().toString());
if(returnChecks(2) != "Default---")
{
myList2.add(returnChecks(2));
myList1.add(returnChecks(2));
myList4.add(returnChecks(2));
Toast.makeText(Vprasalnik1.this, "before: "+returnChecks(2), Toast.LENGTH_LONG).show();
}
addChecks(2, (spinner3.getSelectedItem().toString()));
Toast.makeText(Vprasalnik1.this, "after: "+returnChecks(2), Toast.LENGTH_LONG).show();
}
else
{
if(position != AdapterView.INVALID_POSITION)
{
myList2.add(returnChecks(2));
myList1.add(returnChecks(2));
myList4.add(returnChecks(2));
addChecks(2, (spinner3.getSelectedItem().toString()));
}
}
adapter1.notifyDataSetChanged();
adapter2.notifyDataSetChanged();
adapter3.notifyDataSetChanged();
adapter4.notifyDataSetChanged();
Toast.makeText(Vprasalnik1.this, myList1.toString()+"\n"+myList2.toString()+"\n"+myList3.toString()+"\n"+myList4.toString()+"\n"+checks.toString(), Toast.LENGTH_LONG).show();
break;
case R.id.v1_q1_s4:
if((position != AdapterView.INVALID_POSITION) && (spinner4.getSelectedItem().toString() != "Default---"))
{
findLists(myList2, myList3, myList1, spinner4.getSelectedItem().toString());
if(returnChecks(3) != "Default---")
{
myList2.add(returnChecks(3));
myList3.add(returnChecks(3));
myList1.add(returnChecks(3));
}
addChecks(3, (spinner4.getSelectedItem().toString()));
}
else
{
if(position != AdapterView.INVALID_POSITION)
{
myList2.add(returnChecks(3));
myList3.add(returnChecks(3));
myList1.add(returnChecks(3));
addChecks(3, (spinner4.getSelectedItem().toString()));
}
}
adapter1.notifyDataSetChanged();
adapter2.notifyDataSetChanged();
adapter3.notifyDataSetChanged();
adapter4.notifyDataSetChanged();
Toast.makeText(Vprasalnik1.this, myList1.toString()+"\n"+myList2.toString()+"\n"+myList3.toString()+"\n"+myList4.toString()+"\n"+checks.toString(), Toast.LENGTH_LONG).show();
break;
}
correctSelection();
}
}
At the end of the above code there is a function I call named correctSelection();, that corrects the selection of all spinners, because it doesn't work correctly otherwise - it looks like this:
void correctSelection()
{
inCorrection = true;
spinner1.setSelection(myList1.lastIndexOf(returnChecks(0)));
spinner2.setSelection(myList2.lastIndexOf(returnChecks(1)));
spinner3.setSelection(myList3.lastIndexOf(returnChecks(2)));
spinner4.setSelection(myList4.lastIndexOf(returnChecks(3)));
inCorrection = false;
}
/*it sets the position of all spinners to the last "saved"
(current) item selected, so it corrects the possible index offset that occurs otherwise
(returnChecks(); returns the last item selected from an array in a string format)
PS: To avoid the calling of onItemSelected() in case of programmatically setting the selection
of spinners, I've input a boolean flag (variable "inCorrection"), which is set to false before the
selections are made by "the application" and then set back to false when the code gets run.
*/
To prevent onItemSelected() from being called when you set up the spinner, you can do it like this:
spinner.setOnItemSelectedListener(null);
adapter.notifyDatasetChanged();
spinner.setSelection(0, false);
spinner.setOnItemSelectedListener(onItemSelectedListener);
Explanation:
The framework fires the onItemSelected event when a change in the selection has occurred. It detects a change by registering the current selected position and the previous selected position (mSelectedPostion and mOldSelectedPosition).
When you call notifyDatasetChanged the framework performs various checks to see if the previous selection can be found, so onItemSelected may or may not be called when the spinner is laid out.
By calling setSelection(0, false) these positions are set to 0, possibly detecting a change, but since onItemSelectedListener is null, onItemSelected wont be fired. Position 0 is selected because I guess the "Default---" value is the first position in the list. You can choose another position if you like.
When the spinner is later laid out there is no change, so onItemSelected wont be fired here either.
Note that this has been established by debugging on API level 19 (Android 4.4 KitKat). I don't know if it works on other versions, and I haven't been able to find anything in the documentation to support it.
You can stop the spinner from firing prior to the user making a selection via the optional animation field in the setSelection method. Be sure to order your code this way:
ArrayAdapter<String> spinnerAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, yourList);
spinner.setAdapter(spinnerAdapter);
spinner.setSelection(0, false); //stops spinner from firing prior to user selection
as explained by user1801374 , I made the fix for my case. Just make sure before and after selection index remains same in order to not to invoke the onItemSelected again.
private int spinnerIndex = 0;
spinner.setSelection(spinnerIndex, false);
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener()
{ public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
// Your code here
//I was detaching and reattaching one fragment which was calling the onItemSelected multiple times, recursively.
spinnerIndex = i;
spinner.setSelection(spinnerIndex, false);
return;
}
public void onNothingSelected(AdapterView<?> adapterView) {
// Your code here
return;
}
}

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