Can someone please give me a simple example on how to add three rows to a ListField so that the list shows something like this?
Item 1
Item 2
Item 3
I just want to show a list in which the user can select one of the items and the program would do something depending on the item selected.
I've search all over the internet but it seems impossible to find a simple example on how to do this (most examples I found are incomplete) and the blackberry documentation is terrible.
Thanks!
You probably want to look at using an ObjectListField. Handling the select action is done throught the containing Screen object, I've done this below using a MenuItem, I'm not really sure how to set a default select listener, you may have to detect key and trackwheel events.
Some example code for you: (not tested!)
MainScreen screen = new MainScreen();
screen.setTitle("my test");
final ObjectListField list = new ObjectLIstField();
String[] items = new String[] { "Item 1", "Item 2", "Item 3" };
list.set(items);
screen.addMenuItem(new MenuItem("Select", 100, 1) {
public void run() {
int selectedIndex = list.getSelectedIndex();
String item = (String)list.get(selectedIndex);
// Do someting with item
});
screen.add(list);
You can override the navigationClick method like this:
ObjectListField list = new ObjectListField()
{
protected boolean navigationClick(int status, int time)
{
// Your implementation here.
}
};
final class SimpleListScreen extends MainScreen
{
public SimpleListScreen()
{
super(Manager.NO_VERTICAL_SCROLL);
setTitle("Simple List Demo");
add(new LabelField("My list", LabelField.FIELD_HCENTER));
add(new SeparatorField());
Manager mainManager = getMainManager();
SimpleList listField = new SimpleList(mainManager);
listField.add("Item 1");
listField.add("Item 2");
listField.add("Item 3");
}
}
//add listener so that when an item is chosen,it will do something
private ListField fList = new ListField(){
protected boolean navigationClick(int status, int time) {
System.out.println("omt Click");
return true;
};
};
You can detect the click on each list item by overriding
protected boolean navigationClick(int status,int time)
Then you just need to work out what to do in response to the click. The way I did this was by using an anonymous class, set for each list item.
Related
I'm building a Mac OS app in C# using Xamarin.Mac. I'd like to populate a dropdown (NSPopUpButton) with items that store more information than just their title and index. Specifically I'd like to have each item also hold its own database ID, so when the user chooses that item from the dropdown I can easily fetch the relevant record from the database.
I see that NSPopUpButton uses instances of NSMenuItem, and it's easy enough to subclass NSMenuItem, but there doesn't seem to be a way to insert an instance directly. The AddItem() method only accepts a string (the title of the item) and has no overloads. Is there a way to use custom items, or am I stuck with just title and index to differentiate?
Thanks!
Add your subclass'd NSMenuItem via the NSPopUpButton.Menu.AddItem method.
Example NSMenuItem:
public class MyNSMenuItem : NSMenuItem
{
public string SomeCustomProperty { get; set; }
~~~~
// add all the .ctors w/ base calls....
}
Example usage:
var popUpButton = new NSPopUpButton()
{
Frame = new CGRect(100, 100, 100, 100),
Title = "A pop button",
};
var menuItem = new MyNSMenuItem()
{
Title = "StackOverflow",
SomeCustomProperty = "SomeInstance",
};
menuItem.Activated += (sender, e) =>
{
Console.WriteLine((sender as MyNSMenuItem).SomeCustomProperty);
};
popUpButton.Menu.AddItem(menuItem);
this.View.AddSubview(popUpButton);
I'm new to Xamarin and C#, so apologies in advance for any mistakes I make.
In my app, I have a list of plants. When a plant is selected, I have a detail view of info about the plant. In the detail view, I have a button that adds or removes the plant from a shopping list.
To implement this, I have a class named MyPlant, with a field called InCart, and a method ToggleInCart that the button calls.
(note that I didn't paste in some code to simplify this question as much as possible)
public class MyPlant : INotifyPropertyChanged
{
string name;
bool inCart;
...
public bool InCart
{
set
{
if (inCart != value)
{
inCart = value;
OnPropertyChanged("InCart");
}
}
get { return inCart; }
}
public ICommand ToggleCartStatus
{
get
{
if (_toggleCartStatus == null)
{
_toggleCartStatus = new Command(() => InCart = !InCart);
}
return _toggleCartStatus;
}
I have another class called PlantList, which has a method PlantsInCart that uses LINQ to return an ObservableCollection of MyPlant where InCart is true.
public class PlantList : INotifyPropertyChanged
{
public ObservableCollection PlantsInCart
{
private set { }
get
{
ObservableCollection list = new ObservableCollection(myPlants.Where(i => i.InCart));
return list;
}
}
In my XAML, I have a ListView bound to PlantsInCart.
Everything works as I want EXCEPT when I remove the selected plant, the list doesn't update to show the plant is missing even though the data underneath it is correctly updated. If I refresh the list by going to a different page and coming back, then the list shows the right plants.
I suspect this doesn't work because the change in the InCart field isn't bubbling up high enough to that the ListView hears that it is supposed to update.
Can anybody advise me on the proper way to implement this kind of feature? In other words, how should you implement a scenario where you have a list that should update when a property of an item in the list changes?
I have a table and a button and I want to emit an event ItemsSelected with the selected items of the table when the button is clicked.
The button should not know the table and it should remain only as a stream of clicks.
So this solution is discarded:
final ETable table = ...
PublishSubject<ItemSelected> selected = PublishSubject.create();
button.addSelectionListener(new SelectionListener(){
#Override
public void widgetSelected(SelectionEvent e) {
for (TableItem item : table.getSelection()) {
selected.onNext(new ItemSelected(item));
}
}
});
I would prefer a way to compose the click stream of the button with the item selection stream of the table in order to keep loose coupling between this two elements.
Because the table allows multiple selection I must first scan the items selected in order to emit an event with all the items. Something like:
public static class ItemsSelected<T> {
final List<T> items = new ArrayList<T>();
}
public abstract static class ItemSelection<T> {
public abstract void apply(ItemsSelected<T> selection);
}
public static class ItemUnselected<T> extends ItemSelection<T> {
final T item;
public ItemUnselected(T item) {
this.item = item;
}
public void apply(ItemsSelected<T> selection) {
selection.items.remove(item);
}
}
public static class ItemSelected<T> extends ItemSelection<T> {
final T item;
public ItemSelected(T item) {
this.item = item;
}
public void apply(ItemsSelected<T> selection) {
selection.items.add(item);
}
}
public static class ObservableTable<T> extends Table {
private PublishSubject<ItemSelection<T>> clicks = PublishSubject.create();
public Observable<ItemsSelected<T>> selection = clicks.scan(new ItemsSelected<T>(),
new Func2<ItemsSelected<T>, ItemSelection<T>, ItemsSelected<T>>() {
#Override
public ItemsSelected<T> call(ItemsSelected<T> t1, ItemSelection<T> t2) {
// breaking events immutability
t2.apply(t1);
return t1;
}
});
public ObservableTable(Composite parent, int style) {
super(parent, style);
this.addSelectionListener(new SelectionListener() {
#SuppressWarnings("unchecked")
#Override
public void widgetSelected(SelectionEvent e) {
if (((TableItem) e.item).getChecked())
clicks.onNext(new ItemSelected<T>((T) e.item.getData()));
else
clicks.onNext(new ItemUnselected<T>((T) e.item.getData()));
}
#Override
public void widgetDefaultSelected(SelectionEvent e) {
}
});
}
}
Then, I must combine the table.selection stream with the button.clicks stream in a selectionForAction stream. The idea is that when a ButtonClick is emitted, an SelectionForAction will be emitted if and only if an ItemSelected was previously emitted.
-------S1--U1-----S2---S3--------- table.clicks
(scan)
-------(1)--()---(2)---(2,3)------ table.selection
----O----------O-------------O---- button.clicks
(?)
-----------------------------(2,3) selectionForAction
So, wich operation should I use?
Zip: It doesn't work because if I click the button and later select an item, it should not do nothing, but with zip it will emit an event.
Join: I end up with a "solution" using join but it doesn't seem to be a good one. Somethinkg like:
table.selection.join(button.clicks, new Func1<ItemsSelected,Observable<Long>>() {
#Override
public Observable<Long> call(ItemsSelected t) {
// it doesn't seem a good idea
return Observable.timer(1, TimeUnit.DAYS);
}
}, new Func1<ClickEvent, Observable<Long>>() {
#Override
public Observable<Long> call(ClickEvent t) {
// this makes the ClickEvent be dropped if there is no previous ItemsSelected event emitted
return Observable.timer(1, TimeUnit.MILLISECONDS);
}
}, new Func2<ItemsSelected, ClickEvent, SelectionForAction>() {
#Override
public SelectionForActioncall(ItemsSelected t1, ClickEvent t2) {
return new SelectionForAction(t1.items);
}
});
Any idea?
I've found the operator that I needed to achieve the join behaviour with a very large time unit (DAYS in the example) and a very small one (MILLISECONDS).
With a variant of sample that takes another Observable as the sampler I could emit an event A only after an event of B would be emitted.
In my example the click acts as the sampler and the stream selection emits the events that I'm interested in. (This also requires to ignore the last event that is being emitted when the stream completes).
Another possible solution will be use the buffer(boundary):
The clicks stream would act as the boundary and I could avoid the scan operator because the list of items selected is created by the buffer operator. However with this solution I would not be considering unselection.
So, with sample I've achieved my original goal, however, I'm not happy with the way I handle items unselection and the final list of items selected.
In this case I need to maintain the state of the items selected in order to perform some operation on all of them when a ClickEvent occurs.
I could subscribe to the items selection/unselection and maintain a List of the items selected but then I'll have lost the possibility of compose the clicks observable with the selection observable.
With scan I maintain state and also keep the composability of observables, but representing the list of current selection as an event seems a little forced, in fact this represents a new issue: if I select x items and then click the button, an event with the selection is being emitted as expected, but if neither the items are unselected nor a new one is selected and then click again the button, nothing happens. So, it seems that selection doesn't fit as an event.
I want to paginate my results. First I've tried the classic way and it worked, my dataView retrieves a list with results from database and displays the number of results I want per page.
(Looks like this << <1 2 3 4 5> >> )
final DataView<RequestEntity> dataView = new MyDataView();
dataView.setItemsPerPage(10);
linksContainer.add(new PagingNavigator("pageNavigator", dataView));
<a wicket:id="pageNavigator"></a>
Now I want to retrieve data from database only when the next page is clicked (kind of lazy loading/ lazy pagination). So I modified my DAOObject like this:
query.setMaxResults(entriesPerPage);
It is the same query like before but this time it will take the amount of results I want per page.
And it works, it retrieves as much entries as I want per page. The problem is that I don't know how to display another page. It appears just one page with the first entries from the query. (Looks like this << 1 >>)
My idea is to use links instead of AjaxPagingNavigator to display pages from 1 to 5 and when the link is clicked the query is executed. I don't think my idea is good. Can you help me? I hope my question isn't too stupid.
Thanks
Done! All I needed to do is to create IDataProvider that knows everything. If you create it you don't need to worry about the size( about tricking it to show more pages).
IDataProvider dataProvider = new IDataProvider<RequestEntity>() {
RequestEntityDAOExtra requestEntityDAOExtra =
((MyApp) getApplication()).getMyRequestDAO();
#Override
public Iterator<? extends RequestEntity> iterator(long first, long count) {
List<RequestEntity> entitiesByDomainList = requestEntityDAOExtra.getEntityByDomain(
domainInput.getModelObject(), (int) count, (int) first);
return entitiesByDomainList.iterator();
}
#Override
public long size() {
return requestEntityDAOExtra.getEntityByDomainCount(domainInput.getModelObject());
}
#Override
public IModel<RequestEntity> model(final RequestEntity requestEntity) {
return new LoadableDetachableModel() {
#Override
protected RequestEntity load() {
return requestEntity;
}
};
}
#Override
public void detach() {
}
};
final DataView<RequestEntity> dataView = new MyDataView(dataProvider, 10);
private class MyDataView extends DataView<RequestEntity> {
public MyDataView(IDataProvider dataProvider, int i) {
super("linksList", dataProvider, i);
}
#Override
protected void populateItem(final Item<RequestEntity> item) {
.....
}
}
Im getting crazy about this issue. I implemented a ListView which you can add/remove TextField dinamically, but only the last TextField is removed.
An example:
// Object type which is used in the list
public class ExampleObject implements Serializable{
private String keyword;
public String getKeyword() {
return this.keyword;
}
public void setKeyword(String s) {
keyword = s;
}
}
//ListView
List<ExampleObject> keywordList = new ArrayList<ExampleObject>();
keywordList.add(new ExampleObject());
ListView keywordView = new ListView("keywordView", keywordList) {
#Override
protected void populateItem(final ListItem item) {
ExampleObject model = (ExampleObject) item.getModelObject();
item.add(new TextField("subKeyword", new PropertyModel(model, "keyword")));
// keyword remove link
AjaxSubmitLink removeKeyword = new AjaxSubmitLink("removeKeyword", myForm)
{
#Override
protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
ExampleObject selected = (ExampleObject) item.getModelObject();
// I also tried deleting by index. println shows the
// selected object is the element I want to remove, so why always
// remove last object of the list?
keywordList.remove(selected);
if (target != null) {
target.addComponent(myForm);
}
}
};
item.add(removeKeyword);
// keyword add link
AjaxSubmitLink addKeyword = new AjaxSubmitLink("addKeyword", metadataForm)
{
#Override
protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
keywordList.add(new ExampleObject());
if (target != null) {
target.addComponent(myForm);
}
}
};
item.add(addKeyword);
}
keywordView.setReuseItems(true);
metadataForm.add(keywordView);
Any help would be very appreciate, because I thing this issue is really a very stupid mistake but I cant get it!
Thanks
It might be as simple as getting rid of the line
keywordView.setReuseItems(true);
The reuseItems flag is an efficiency so that the page does not rebuild the ListView items unnecessarily, but it can lead to confusion such as what you're seeing.
ListView really wasn't made for use with forms though, and you'll probably be better off with another tactic entirely.
This blog entry on building a list editor form component might be useful. It will need some changes if you're not on Wicket 1.4, but similar stuff is definitely possible in Wicket 1.3, and the comments have some hints.
Read the javadoc of ListView#setReuseItems():
"But if you modify the listView model object, than you must manually call listView.removeAll() in order to rebuild the ListItems."
You can not use a ListView this way. Either use the members of ListView provided:
removeLink(java.lang.String id, ListItem<T> item)
and
newItem(int index)
but, I never used those. If I have to display a List and be able to add remove Items dynamically, I prefer the RefreshingView.
If you do use FormComponents inside a RefreshingView, make sure you set a Reusestartegy (setItemReuseStrategy())
Bert