I have a listbox that I am using as a scrollable “click” menu (thank you Michael Bujardet). That works great but I have a placement question.
I have several controls that use this menu that all exist in a web container control. The web container control has a top and left at 0 on the web page. It’s always the width of the page and it’s 160 pixels less than the height. I may have more controls though than fit in that visible area. So the web container control scrolls to bring controls into view. So for example, right now in my debug build I have running, my container control has a height of 965 pixels. But I have controls that are at 1070 and 1220 pixels. But I am always viewing just 965 pixels (or it could be less if I resize my page smaller).
Now this menu (listbox) may be very large and if it has more items in it than the height of the container control I set it to the height of the container control. I want it to then when active sit on the page with the top of the menu at basically 0 and the bottom at the bottom edge of the container control. Problem is, after I scrolled the container, the zero position is up beyond the top visible edge. So if I set the top of the menu (listbox) at 0 when activated, it screws things up when I am scrolled down the page. How can I center this in the viewable part of the container control? I don’t see a scroll offset or scroll value property anywhere for the Web Container Control. I thought about using the top value of the particular control that brings up the menu as an offset but that doesn’t necessarily give me what I want as the controls height from the bottom of the container control can vary due to scroll position.
There is no ScrollPosition in the WebListBox. Which I personally find utterly surprising, not to say ridiculous. So there is no way I know of to set the first visible row to a precise cell. Christian Schmitz has filed a feature request 32620 - Need ScrollPosition on Weblistbox in March of this year, it has been reviewed and hopefully some day this basic function may be added. In the meantime, we have to live in preposterous poverty.
You can reset the ListBox to zero by storing the content of the WebListBox into an array, DeleteAllRows and load them back with AddRows.
In researching that I just found a nasty bug : in Desktop, string = ListBox(-1,-1) copies the content of all the listbox as tab delimited into string.
In WE, you get an Out Of Bound exception, with the explanation ‘Attempted to access cell -1,-1 but limit is xx,xx’
34467 - WebListBox.Cell -1 value out of bound
I also tried to create a listbox dynamically but the method described in the LR with control array does not work, and I do not want to use a WebContainer. Is there any way to do that ?
Wait. I found 27412 - cannot clone controls using XOJO documentaton on a web application where Paul states :
[quote]Use WebContainers (refer to the Containers section in the User Interface Guide) to dynamically create controls at run-time in web applications.
The older User Guide stuff should now be completely removed from the online wiki.[/quote]
An extremely hackish way to have a working ScrollPosition would be to use a “view” ListBox for the UI, coupled with a separate ScrollBar, that would show a “target window” into the values of the real ListBox set as invisible. The code in MouseWheel and in the ScrollBar would then simply insert new rows from the invisible WebListBox when scrolling up while deleting the last rows, and the other way around when scrolling down.
It is even possible to devise a class around that. But as much as I love a challenge, I did not feel like spending a few hours on getting that to work. It is feasible, though.
[quote=111717:@Michel Bujardet]There is no ScrollPosition in the WebListBox. Which I personally find utterly surprising, not to say ridiculous. So there is no way I know of to set the first visible row to a precise cell. Christian Schmitz has filed a feature request 32620 - Need ScrollPosition on Weblistbox in March of this year, it has been reviewed and hopefully some day this basic function may be added. In the meantime, we have to live in preposterous poverty.
[/quote]
Well, I would like to get the scroll position of the weblistbox. However, I in my post above, I was trying to get the scroll position of a WebContainer. I did figure out a hack to sort of get that position. It works pretty well.
The WebContainter has a ContentsScrolled event that occurs whenever it is scrolled. In that event, you get a set of X,Y coordinates. This represents the new position of the upper left hand corner of the page. I have created two properties for the container control called something like XOffset and YOffset. When the event occurs, I update the properties with the values of X and Y. Then I use those properties to calculate control positions in the page.
It works but there seems to be a little bit of error with it that I need to figure out. A scroll position would be way better.
There used to be a special “Add” directive. Let’s say you have a UI placed Web pop-up menu called MyUIWebControl
For i = 0 to NumberofDesiredControls
Dim NewControl as WebPopUpMenu
NewControl = self.AddMyUIWebControl
Next
I am not sure if this is still in the framework or not. I just tried compiling an old, old version of my web app that still used these and the compilers did not throw any errors. I got some runtime errors due to other reasons as my settings file format has changed since then.
Again, not sure if they took this out of the framework or not.
If we added a scrollposition property it would be reading the same values that you get from the ContentsScrolled event. The advantage of the event is that we don’t have to send the information from the browser unless you’re interested in it. Otherwise we’d have to transmit the info all the time, even if the developer didn’t care about it, using up precious bandwidth.
May I ask why you don’t want to use a WebContainer?
Please don’t use these “special” Add… commands. I know they’re there and I know Thom blogged about their use years ago, but they’re really unpredictable and cause lots of other bugs to manifest.
Not being able to get a row height is really annoying!
But one issue I found here is that if you have a routine in MouseMove to highlight the row the mouse is over when you move the mouse, there is no way to correctly know what row you are in once the scroll has happened. So it screws that up. If there was a way to get a row position based on mouse position, that would be great, but I don’t see a way to do that.
I know that in the past there’s been significant bugs with them when using them as control arrays unless you use the EmbedWithin directive. That works pretty well. Not sure if the other bugs have been fixed. But while containers are convenient sometimes they are a pain when trying to access a control that is outside the container. You either have to use explicit references or pass the other control into the container. Not so when you are just dealing with all your controls on a single page.
I’m not sure why Michael doesn’t want to use one, but I just know that it adds another layer of complexity to the code (but I still use multiple container controls in my app).
[quote]
Please don’t use these “special” Add… commands. I know they’re there and I know Thom blogged about their use years ago, but they’re really unpredictable and cause lots of other bugs to manifest.[/quote]
OK. I thought those had maybe even been taken out. They were somewhat of a hack that I know Thom threw in before the first Web Edition release was even out. I’m not using them any more as I moved everything to containers.
[quote=111753:@Jon Ogden]The WebContainter has a ContentsScrolled event that occurs whenever it is scrolled. In that event, you get a set of X,Y coordinates. This represents the new position of the upper left hand corner of the page. I have created two properties for the container control called something like XOffset and YOffset. When the event occurs, I update the properties with the values of X and Y. Then I use those properties to calculate control positions in the page.
It works but there seems to be a little bit of error with it that I need to figure out. A scroll position would be way better.[/quote]
I had not quite understood what you needed, and believed you needed to set the ScrollPosition, not just get it.
I am sorry but if I compare to the Desktop ListBox ScrollPosition is independent from the RowHeight : if you set it to 4, row 4 appears on top of the ListBox. And when you get it, it gives you the first row. I do not understand why variable RowHeight would render such feature unavailable. For getting/Setting the first row displayed, I maybe mistaken, but there must be information in the code for the control to display correctly, right ?
I have no objection using an additional control if there is no other way. I was just surprised that a simple method used in Desktop was not available for Web. As Jon mentions it, though, it does add a layer of complexity. Somewhat less elegant. But you may have noticed I sort of affectionate workarounds, so it’s alright.
OK. The approach I posted at the end of my previous post is a way to have a ScrollPosition that is both Get-able and Set-able, and a select. It is probably less hackish than much more than a simple workaround as I usually post. Hence I will not work on that unless I am reasonably certain I will not waste efforts on that if then some whim makes that worthless. Often enough in this forum I take time to actually test before I post a suggestion, just to see the OP drop the idea without a thank you, and well… It can be frustrating…
Intrinsically a WebListBox is a set of data and a control that displays it, and allows it to be modified. What I have in mind is just another listbox which contains, displays and let the user work an a subset of the data contained in a larger listbox. With a one column listbox, it could be composed of a simple TextField, which mirrors one of the cells in a ListBox. Any change in the TextField is made to be reflected in the ListBox Cell, and any change in the ListBox data is reflected in the TextField content. With that concept, changing the cell the textfield refers to effectively scrolls through the ListBox up and down.
What I plan to do is to use a listbox with a number of columns identical to the number of columns displayed, so it will not scroll. Let’s call it the “View”. And it mirrors the true listbox I will call “Reference”. In your case the View contains only one column, so the first row is relative to a cell in the reference that will effectively be the ScrollPosition. It is not really different from what we would do with a form that displays addresses in regard to a database, really.
Where it will require probably time and efforts is to fine tune the link between the view and reference ListBoxes.