I need to select an item from a list box that contains objects of my class. Here is my code:
the load event:
private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
{
XDocument loadedData = XDocument.Load("file.xml");
var data = from query in loadedData.Descendants("element")
select new myClass
{
First = (string)query.Element("first"),
Second = (string) query.Element("second")
};
List<myClass> d = data.ToList<myClass>();
myList = d;
myListBox.ItemsSource = data;
}
and then my button which is supposed to change the selected Item:
private void button1_Click(object sender, RoutedEventArgs e)
{
myListBox.SelectedItem = myList[100];
}
am I doing something wrong here?
myList isn't the collection you've bound to the list.
Either make d a wider scoped variable and refer to that in button1_click
or
store data in myList rather than a copy of it.
For efficiency, I would set the ItemsSource to 'd' rather than 'data'. The enumeration returned by the linq query is lazy, so it gets evaluated every time the UI updates. The array you have is eagerly created, so later lookups are fast.
Looks like a little bug here. I was able to inconstantly replicate a similar problem.
I used the standard VS template for a Databound Application. The template comes with some sample data and a populated list box. I added a button which set the selected item to the 15th item in the collection. This worked as expected. However, when I scrolled the list up to the top it wouldn't return to the 15th record when I clicked the button. Taking a guess here, what you're running into is another symptom of the same problem.
To solve this I first set the SelectedIndex to -1 which essentially deselects the item.
private void button1_Click(object sender, RoutedEventArgs e)
{
myListBox.SelectedIndex = -1;
myListBox.SelectedItem = myList[100];
}
I'm curious if this also solves your problem.
Related
Unity3D 2018.2
So I have a canvas that gets deactivated and reactivated at users choice. I have a List filled with transforms in which I populated the Grid with. I also have another List to hold all the images that will be used to populate the Grid with, since what the grid is being populated with are buttons containing the transform. For example if I click the button and run Debug.Log("transform.name"), I should see all my different transforms.
Problem 1: Every time this canvas gets enabled or disabled, the grid
keeps adding 1 element under the initial one, and after being
enabled/disabled again, another element is instantiated under that
one.
+
Problem 2: Also none of these instantiated buttons get called. Maybe
the problem here is due to the 1st problem?
Here is the code I have for inside the button I have
public class SatelliteButton : MonoBehaviour {
[SerializeField]
private Image myIcon;
public void SetIcon(Sprite mySprite)
{
myIcon.sprite = mySprite;
}
public void OnMouseEnter()
{
Debug.Log(transform.name);
}
}
Here is the code for populating the grid
public class SatelliteGridControl : MonoBehaviour {
private List<Transform> satelliteListFromPlanet;
[SerializeField]
private GameObject buttonTemplate;
[SerializeField]
private GridLayoutGroup gridGroup;
[SerializeField]
private List<Sprite> iconSprites;
// Use this for initialization
void OnEnable()
{
getSatellitesInPlanet();
genInventory();
}
// Get Satellites
private void getSatellitesInPlanet()
{
satelliteListFromPlanet = new List<Transform>();
// Get current planet
Transform currentPlanet = GameObject.FindGameObjectWithTag("MainCamera").GetComponent<HandleCamera>().targetToLookAt;
// Check inside for satellites
foreach (Transform satellite in currentPlanet)
{
// Check transform for tag
if (satellite.CompareTag("Satellite"))
{
// Add each transform from planet to array
satelliteListFromPlanet.Add(satellite);
}
}
}
// Handle Grid
private void genInventory()
{
if (satelliteListFromPlanet.Count < 6)
{
gridGroup.constraintCount = satelliteListFromPlanet.Count;
}
else
{
gridGroup.constraintCount = 5;
}
foreach (Transform sat in satelliteListFromPlanet)
{
GameObject newButton = Instantiate(buttonTemplate) as GameObject;
newButton.SetActive(true);
newButton.GetComponent<SatelliteButton>().SetIcon(iconSprites[Random.Range(0, iconSprites.Count)]);
newButton.transform.SetParent(buttonTemplate.transform.parent, false);
}
}
}
I appreciate the help! Learning about grid layouts with List<>!
In genInventory() you Instantiate a new button for every Transform in satelliteListFromPlanet. Since only 1 is added it seems that your list only contains 1 element.
But you never destroy/remove this Instantiated GameObjects, so the next time you re-enable the object, OnEnable will be called again and new prefabs are Instantiated.
Solution:
Make sure to store the Instantiated objects somewhere e.g.
private List<GameObject> instances = new List<GameObject>();
//....
foreach (Transform sat in satelliteListFromPlanet)
{
GameObject newButton = Instantiate(buttonTemplate) as GameObject;
newButton.SetActive(true);
newButton.GetComponent<SatelliteButton>().SetIcon(iconSprites[Random.Range(0, iconSprites.Count)]);
newButton.transform.SetParent(buttonTemplate.transform.parent, false);
instances.Add(newButton);
}
And than you can destroy them when you disable the object:
private void OnDisable()
{
foreach(var instance in instances)
{
Destroy(instance);
}
}
Problem 1: Every time this canvas gets enabled or disabled, the grid keeps adding 1 element under the initial one, and after being enabled/disabled again, another element is instantiated under that one.
Right now you're calling getSatellitesInPlanet() on SatelliteGridControl's OnEnabled() method. This method is called every time the object is set to active. If you just want to call your method once, use Start.
Problem 2: Also none of these instantiated buttons get called. Maybe
the problem here is due to the 1st problem?
I don't think the problems are related. Can you confirm that your buttonTemplate prefab has an Image element and its RaycastTarget is enabled?
Just one tip, I would set the type of buttonTemplate to SatelliteButton, not GameObject. That way you can instantiate it as type SatelliteButton and avoid the need to call:
newButton.GetComponent<SatelliteButton>()
From various questions, I know it is impossible to create DataTemplate from the code behind without using the XamlReader. So I want to ask if there is a way to programatically generates the UI for each Item in a ListView. I don't seem to find any relevant event handler or member of ListView for this purpose. Ideally, I want the ListView to invoke my handler code to generate UI for each data item it needs to display.
Imitating the official XamlTreeView sample, I have tried overriding some ListView method such as PrepareContainerForItemOverride but this won't work. The solution I found is as #JustinXL suggests: producing ListViewItem and insert them to the ListView->Items directly
//assume that items is a list of items we want to bind
myListView->Items->Clear();
for(auto i : items)
{
ListViewItem^ v = ref new ListViewItem();
v->Content = GenerateUIFor(i);
myListView->Items->Append(v); // NOTE: a wrapping ListViewItem is required!
}
To support usual data binding, it would be best to make the data structure to cache the generated UI. For example,
ref class MyDataStructure
{
public:
property ListViewItem^ Item
{
ListViewItem^ get()
{
if (_item == nullptr)
GenerateUI();
return _item;
}
}
void GenerateUI()
{
_item = ref new ListViewItem();
_text_block = ref new TextBlock(); // sample
_item->Content = _text_block;
UpdateUI();
}
// Invoke this when changing the state of this object
void UpdateUI()
{
if (_text_block != nullptr) // sample
{
_text_block->Text = this->ToString(); // sample
}
}
private:
ListViewItem^ _item;
TextBlock^ _text_block;
};
The downside of this is of course we can't make use of data virtualization. But it works properly for small set of data. For large set, one can use website's approach with Next and Prev button to load next page or go back to previous page.
ItemContainerGenerator should let you construct the entire UI for an item inside a list view. Unfortunately there doesn't appear to be much in the way of non MSDN documentation/samples for this.
Alternatively if you can maintain a list of all the DataTemplates you might need to show, you could use a DataTemplateSelector to choose which DataTemplate you want to show for each individual item.
I'm doing my controller. When I click on an item in my ListWidget, the following method is called :
void ContactBookController::setCurrentlySelectedItem(QListWidgetItem *item)
{
setCurrentItem(*item);
m_window.setEditButtonsState(true);
}
And the setCurrentItem() method is as follows : (m_current_item is a private variable):
void ContactBookController::setCurrentItem(const QListWidgetItem ¤t_item)
{
m_current_item = current_item;
}
Now, when I create a contact, I add an item to the QListWidget, but I also create a Contact object, but I also bind them together in a QHash so I know what QListWidgetItem corresponds to what Contact. In short, here is what I did :
void ContactBookController::createContact()
{
auto new_contact = m_contact_book.createContact();
if(new_contact != nullptr)
{
new_contact->setName(tr("New contact"));
}
auto list_item = m_window.createContact(new_contact->getName());
m_window.clearSelection();
m_contact_map.insert(list_item, new_contact);
}
Now, when clicking on a QListWidgetItem, I activate the edit button and I would like to retrieve the corresponding Contact object. However, when doing this, the Contact object doesn't seem to be correct. Indeed, if I use a method on him (like getName()), my application instantly crashes.
Here is what I did :
void ContactBookController::editContact()
{
auto list_item = m_current_item;
auto contact = m_contact_map.value(&list_item); /* doesn't work */
}
My hash table is declared as such :
QHash<QListWidgetItem*, Contact*> m_contact_map;
Any idea what I did wrong ?
Your hash has the type QHash<QListWidgetItem*, Contact>. So, mapping a item pointer to a contact value.
When you save the mapping for a specific item with m_contact_map.insert(list_item, new_contact), you add a mapping from the item pointer to the contact. But when you try to retrieve the contact with m_contact_map.value(&list_item), you look up the value for the pointer to the local list_item variable, which points to somewhere on the stack, and has nothing to do with the pointer to the item that is shown in the view.
Either you need to save to pointer to the selected value, i.e. make m_current_item a QListWidgetItem *m_current_item, or you simply use QListWidget::currentItem() to retrieve the current item without the need for an additional member variable.
(Side note: You should check for currentItem() != nullptr, since a list widget does not necessarily has an item selected.)
I am working on a very simple program, looking like this:
public class WicketApplication extends WebApplication implements Comparable<Object>{
private List<Person> persons = Arrays.asList(
new Person("Mikkel", "20-02-91", 60169803),
new Person("Jonas", "02-04-90", 86946512),
new Person("Steffen", "15-07-90", 12684358),
new Person("Rasmus", "08-12-93", 13842652),
new Person("Michael", "10-10-65", 97642851));
/**
* #see org.apache.wicket.Application#getHomePage()
*/
#Override
public Class<? extends WebPage> getHomePage() {
return SimpleView.class;
}
public static WicketApplication get() {
return (WicketApplication) Application.get();
}
/**
* #return #see org.apache.wicket.Application#init()
*/
public List<Person> getPersons() {
return persons;
}
public List<Person> getSortedList(){
return Collections.sort(persons);
//This won't work before implementing comparator i know, but how??
}
#Override
public void init() {
super.init();
// add your configuration here
}
#Override
public int compareTo(Object o) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
}
That was the class where i just put my people into a list.
public class SimpleView extends SimpleViewPage {
public SimpleView() {
ListView persons = new ListView("persons", getPersons()) {
#Override
protected void populateItem(ListItem item) {
Person person = (Person) item.getModelObject();
item.add(new Label("name", person.getName()));
item.add(new Label("birthdate", person.getBirthdate()));
item.add(new Label("phone", person.getPhone()));
}
};
add(persons);
add(new Label("size", "Number of people " + getPersons().size()));
}
}
And here is what i do with the people.
Basicly i want the program to show a table with all the data(this already works).
Now i want to be able to sort them. But i can't for the life of me figure it out. I'm still rather new at programming, and i want to have a button below my table that can sort on name, bday or phone number. Was thinking about trying to Comparable, but can't remember it that well, and not sure how it works with Wicket..
Thanks for the help in advance :)
What you need is the DataView component, which provides all the support you need for sorting (and paging, should you require it later on).
Here's a working example, if you click on the "Source Code" link in the top right corner, you can see that most of the things you want from a sortable table work out of the box. All you need is to create a suitable data provider.
If you use DataView with a SortableDataProvider, you don't need to worry about writing your own dynamic Comparator. (Which is not a terribly hard task itself, but it's easy to get it wrong.)
I'm trying to create a custom lookup filter in a dialog in AX.
I've followed the instructions in this post x++ filter lookup in dialog and am getting a Stack Trace error -- FormRun object not initialized -- when I'm run my code.
What I am trying to do is filter the lookup() for the ConfigId EDT based on the selection from the ItemId EDT. I have the custom lookup() ready to go and working properly, I just can't get it called from my dialog box.
public Object dialog(DialogRunbase _dialog, boolean _forceOnClient)
{
DialogRunBase dialog;
;
dialog = super(_dialog, true);
dialog.caption('#RID2885');
dfItem = dialog.addField(typeid(ItemId));
dfInventLoc = dialog.addField(typeid(InventLocationId));
dfReplaceCost = dialog.addField(typeid(PdsCost));
dfItemConfig = dialog.addField(typeid(ConfigId));
dfColorId = dialog.addField(typeid(InventColorId), '#RID101');
return dialog;
}
Here's the call to the lookup():
void Fld_7_lookup()
{
Formrun fr = this.dialogModify().parmDialog();
Object control = fr.controlCallingMethod();
;
ConfigTable::lookupConfigIdSimple(control, dfItem.value());
}
And this is where it keeps getting the Stack Trace error:
public void dialogPostRun(DialogRunbase _dialog)
{
;
super(_dialog);
**_dialog.formRun().controlMethodOverload(true);** // Causes Stack Trace error
_dialog.formRun().controlMethodOverloadObject(this);
}
I have tried multiple configurations with the dialog box. When the code reaches that point, it still has information passed in from the dialog() method, but when it goes to get the FormRun, that object is blank.
Could someone please help me understand why there is no FormRun object associated with the DiaglogRunBase that is passed-in?
Thanks.
Mayby you should call super(_dialog) last in the dialogPostRun method.
Have a look on a similar solution and one more.
Did you check to see if your class is set to run at "Called From"?
Here is an example code for overriding the modified method. Maybe lookup has the same requirements:
public void dialogPostRun(DialogRunbase _dialog)
{
// Must be overriden to enable overriding modified method
;
_dialog.dialogForm().formRun().controlMethodOverload(true);
_dialog.dialogForm().formRun().controlMethodOverloadObject(this);
_dialog.formRun().controlMethodOverload(true);
_dialog.formRun().controlMethodOverloadObject(this);
super(_dialog);
}
And for the custom method:
boolean Fld2_1_modified()
{
FormStringControl c = dialog.formrun().controlCallingMethod();
boolean ret;
;
ret = c.modified(); // Super() Call the FormControl ->modified
dlgCustomField.value(MyClass::someMethod(dlgCustomField.value())); // example
return ret;
}