I am trying to create a List which behaves like, for example, the Finder Menu on my Mac. In other words if I click on a List Item, keep my mouse down and move up and down the List I want the Selected Item to change.
In my Flex application if I click on my List and then, with the mouse still down, move up and down the List the Selected Item remains the same.
Any advice would be gratefully received.
Thanks
In StackOverflow tradition I am posting a solution to my own problem after working at it more:
I had an ItemRenderer on my List. In the ItemRenderer I declared a variable to hold a reference to the owning List.
private var _parentList:List;
In the 'set data' function I set this variable to the owner List.
override public function set data(value:Object):void {
super.data = value;
// Check to see if the data property is null.
if (value == null)
return;
// If the data property is not null.
// Get a reference to the parent list.
_parentList = this.owner as List;
...
I then added an EventListener to listen for MouseDown events.
// Attach an eventListener to the ItemRenderer.
this.addEventListener(MouseEvent.MOUSE_OVER, onMouseOver);
...
My onMouseOver handler looks like this.
private function onMouseOver(event:MouseEvent):void {
//trace(data.LocationName);
if (event.buttonDown == true) {
_parentList.selectedIndex = itemIndex;
}
}
So with this in place I can mouse-down on my List and keeping the mouse button depressed move up and down the List with the List Item beneath the cursor always being selected. The final piece to this is to ensure that the List responds to the selectedIndex being set by the ItemRenderer. When the user changes the selectedIndex property by interacting with the control, the control dispatches the change and changing events. When you change the value of the selectedIndex property programmatically, it dispatches the valueCommit event. To ensure I responded to my programmatic changing of the selected list item I added a handler to the valueCommit event.
<s:List
id="locationsList"
dataProvider="{presenter.locations}"
itemRenderer="itemrenderers.locationListItemRenderer"
useVirtualLayout="false"
width="1869.698" height="1869.698"
y="65.151" x="65.151"
borderVisible="true"
borderColor="{presenter.backgroundColour}"
contentBackgroundAlpha="0"
contentBackgroundColor="0xff336c"
labelField="label"
change="presenter.onLocationListChange(event)"
valueCommit="presenter.onLocationListValueCommit(event)">
<s:layout>
<s:BasicLayout />
</s:layout>
</s:List>
So far it seems to work fine. Hope it helps.
Related
My environment is Python 2.7, running on Windows 7.
I'm trying get a Tkinter Listbox to trigger a callback in response to the user changing the 'active' item (i.e. the item with focus). I'm using a binding to the <<ListboxSelect>> event to make this happen, and it's working -- sort of.
The callback itself is supposed to check what the new active item is, and carry out some processing accordingly. This logic operates the way I expect when I change the active item via the up/down arrow keys. But when I point & click on a new item instead, the code mistakenly identifies the prior active item as the current one.
Here's a stripped-down code sample that illustrates the behavior I'm getting:
import Tkinter as tk
#Root window
root = tk.Tk()
#Callback to show focus change
def updateDisplay(*args):
focusIndex = str(lb.index(tk.ACTIVE))
ctrlFI.set('Focus is at index '+focusIndex)
#Control variables
ctrlLB = tk.StringVar()
ctrlFI = tk.StringVar()
#Widgets
lb = tk.Listbox(root,
width=20, height=10,
relief=tk.FLAT,highlightthickness=0,
selectmode=tk.EXTENDED,
activestyle='dotbox',
listvariable=ctrlLB)
lbl = tk.Label(root,
justify=tk.LEFT, anchor=tk.W,
textvariable=ctrlFI)
lb.grid(row=0,column=0,sticky=tk.NW,padx=(5,0),pady=5)
lbl.grid(row=1,column=0,columnspan=2,sticky=tk.NW,padx=5,pady=5)
#Listbox binding to trigger callback
lb.bind('<<ListboxSelect>>',updateDisplay)
#Initializations to prep GUI
ctrlLB.set('Index0-entry Index1-entry Index2-entry Index3-entry Index4-entry')
ctrlFI.set('Ready')
#Begin app
tk.mainloop()
Here are the results when you use the arrow keys:
But here's what you get when you click with the mouse:
The information 'lags' one behind, showing the prior selection instead. (If you click the same item a second time, it 'catches up.')
So my questions are:
What is causing the discrepancy?
How do I fix it so the mouse click gives the right result?
The active item is not necessarily the same as the selected item. When you press the mouse down it changes the selected value but it does not change the active item. The active item only changes once you release the mouse button.
You should be able to see this by clicking and holding the mouse button over an item that is not currently selected. When you do, you'll see something like this:
In the above image, the active item is the one surrounded by a dotted outline. The selected item is in blue. When your code displays the 'focus', it's displaying the active element rather than the selected element.
If you want the selected item, you need to use curselection to get the index of the selected item. It returns a tuple, so in extended mode you need to get the first element that is returned (eg: lb.curselection()[0]). Be sure to handle the case where curselection returns an empty string.
Flex How can I change item in dataProvider when Items(multiple selection) is selected or deselected in the mx:List
I just want my data reflect what items I selected in the list dynamically. Base on that do some sorting with the list, for example make selected items first in the list when they are selected, and go back to original place when items are deselected....
You can use the IViewCursor to get/add/remove items of the list.
Below is a code example of how to create the cursor, based on that you will just need to apply the logic you need.
var col:ICollectionView = ICollectionView(list.dataProvider);
var myCursor:IViewCursor = col.createCursor();
//do the logic using the myCursor functions
...
//refresh the collection to the changes reflect in the list
col.refresh();
Here you can check some more info about it.
You can add an event listener to your list so that whenever a selection/deselection occurs it triggers.
<s:List id="myList"
labelField="firstName"
change="selectionChangedHandler(event)"
dataProvider="{peopleArray}">
</s:List>
....
protected function selectionChangedHandler(event:IndexChangeEvent):void
{
var currentIndx:int = event.currentTarget.selectedIndex;
var currentDataItem:Object = event.currentTarget.selectedItem;
peopleArray.removeItemAt(currentIndx);
peopleArray.addItemAt(currentDataItem,0);
peopleArray.refresh();
}
I haven't run it but you may need to set selection on refreshed list too.
I have a list extending Ext.dataview.List.
I would like to play an animation in only one of the list items.
If it is triggered by the itemTap, it is easy, because the callback provides a third argument, I just run the animation on it. (I mean Ext.Anim.run).
But what if I need to animate the n-th element independently from the list, like triggered by a user tap on a separate button?
Thanks
Let's say you have a list which has the following config :
xtype:'list',
cls: 'myList',
...
Then you can access its DOM element with :
var items = Ext.DomQuery.select('.myList .x-list-item');
It will returns all the items of the list with the cls 'myList' so be sure to have only one list with this class.
From there you can do whatever you want with it like hiding the second item :
items[1].style.display = 'none';
Hope this helped
I am writing an app with an appbar and item list. I want to add some buttons to the appbar which should appear only when the list item is selected.
So, how to show an additional button on an appbar when the item of the list is selected?
This is Windows 8 Metro style C#/XAML application.
<AppBar x:Name="bottomAppBar" IsOpen="True" IsSticky="True">
...
private void itemGridView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (itemGridView.SelectedItems.Count > 0)
{
nextButton.Visibility = Windows.UI.Xaml.Visibility.Visible;
}
else
{
nextButton.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
}
}
Create the additional app bar button and set its Visibility property to Collapsed.
In the SelectionChanged event handler of the list, set the buttons Visibility property to either Visible or Collapsed depending on whether the list item is being selected or deselected.
Set AppBar.IsOpen property instead of Visibility.
I'm working on a project that uses a master page and content pages. My masterpage a navigation bar:
<asp:Menu ID="NavigationMenu" runat="server" CssClass="menu" EnableViewState="false" IncludeStyleBlock="false" Orientation="Horizontal">
<Items>
<asp:MenuItem NavigateUrl="~/ProjectPage.aspx" Text="Home" />
<asp:MenuItem NavigateUrl="~/ProductBacklog.aspx" Text="Product Backlog"/>
<asp:MenuItem NavigateUrl="~/SprintBacklog.aspx" Text="Sprint Backlog" />
<asp:MenuItem NavigateUrl="~/MeetingPage.aspx" Text="Meetings" />
<asp:MenuItem NavigateUrl="~/Burndown.aspx" Text="Burndown"/>
<asp:MenuItem NavigateUrl="~/About.aspx" Text="About Us"/>
</Items>
</asp:Menu>
On one of my content pages, I dynamically add sub-menu menuitems to my 'Sprint Backlog' menuitem. There is a button, and everytime the user clicks that button, a sub-menuitem is added, so that when the user hovers over 'Sprint Backlog' in the navigation menu, the submenu comes up. I do this by creating a list of menuitems, creating a new menuitem with (shown text, value, navigationURL), adding the menuitem to the list of menuitems, then saving the list to Session:
protected void btSave_Click(object sender, EventArgs e)
{
menuItemList = (List<MenuItem>)Session["menuItemList"];
if (menuItemList == null)
{
menuItemList = new List<MenuItem>();
}
MenuItem menuItem = new MenuItem("Sprint " + sprintNumber, sprintNumber.ToString(), "SprintBacklog.aspx");
menuItemList.Add(menuItem);
Session["menuItemList"] = menuItemList;
}
In the code-behind for my masterpage, I create a list of menuitems, set the value of the instance of the menuitem from Session, and add childitems to the navigationmenu at the appropriate index. The childitem I am adding are the menuitems from the list of menuitems.
List<MenuItem> menuItemList;
protected void Page_Load(object sender, EventArgs e)
{
menuItemList = (List<MenuItem>)Session["menuItemList"];
if (menuItemList != null)
{
foreach (MenuItem menuitem in menuItemList)
{
NavigationMenu.Items[2].ChildItems.Add(menuitem);
}
}
}
I know that I gave these childitems a value when I created them, but my problem is accessing those values when I am loading the SprintBacklog.aspx content page. Whenever a user clicks on one of the childitems, it will always navigate to SprintBacklog.aspx, but the contents of that page should differ according to which child item they clicked. I need a way to know which childitem they clicked, and access that value to populate my content page.
If someone has a better way for me to carry this whole thing out, I am open for suggestions and change. Otherwise, if my setup can work, and there is a way for me to extract the value of the clicked childitem, I'd really like to know that.
I know if I hard-code the childitems in my masterpage, I can easily get the value, but my problem is that I'm creating the submenu childitems dynamically, and I'm not sure how to access it.
Any help would be really appreciated! Thanks!
-Jose
It's been a long time since I asked this question, and I'm not familiar with how masterpages work anymore, but if anyone is experiencing anything similar, I may have a suggestion.
Each menu item I was creating was linking to SprintBacklog.aspx like so:
MenuItem menuItem = new MenuItem("Sprint " + sprintNumber, sprintNumber.ToString(), "SprintBacklog.aspx");
What I should have done was link to SprintBacklog.aspx, but also add a parameter to the request with the sprint ID.
Then the controller which handles the rendering of SprintBacklog.aspx would read the parameter and fetch the appropriate data to render.