DataGridView: how to make scrollbar in sync with current cell selection? - visual-studio-2005

I have a windows application with DataGridView as data presentation. Every 2 minutes, the grid will be refreshed with new data. In order to keep the scroll bar in sync with the new data added, I have to reset its ScrollBars:
dbv.Rows.Clear(); // clear rows
SCrollBars sc = dbv.ScrollBars;
dbv.ScrollBars = ScrollBars.None;
// continue to populate rows such as dbv.Rows.Add(obj);
dbv.ScrollBars = sc; // restore the scroll bar setting back
With above codes, the scroll bar reappears fine after data refresh. The problem is that the application requires to set certain cell as selected after the refresh:
dbv.CurrentCell = dbv[0, selectedRowIndex];
With above code, the cell is selected; however, the scroll bar's position does not reflect the position of the selected cell's row position. When I try to move the scroll bar after the refresh, the grid will jump to the first row.
It seems that the scroll bar position is set back to 0 after the reset. The code to set grid's CurrentCell does not cause the scroll bar to reposition to the correct place. There is no property or method to get or set scroll bar's value in DataGriadView, as far as I know.
I also tried to set the selected row to the top:
dbv.CurrentCell = dbv[0, selectedRowIndex];
dbv.FirstDisplayedScrollingRowIndex = selectedRowIndex;
The row will be set to the top, but the scroll bar's position is still out of sync. Not sure if there is any way to make scroll bar's position in sync with the selected row which is set in code?

I found an answer to resolve issue. As I mentioned that the control does not have methods or properties to set the correct scroll bar value. However, the scroll bar and the DatagridView content will display correct if there is an interaction directly towards to the UI such as touch the scroll bar or grid cell. It looks like that the control needs to be refocused and a repaint.
Simply use the following codes does not cause the scroll bar reset:
dgv.Select();
// or dbv.Focuse();
The way I found is that I have to make the DatagridView control disappear to back again. Fortunately, I have a tab control with several tabs. Then I switch the tab to get scroll bar reset:
int index = myTabCtrl.SelectedIndex;
if (index == (myTabCtrl.TabCount)) {
dgv.SeletecedIndex = 0;
}
else {
dgv.SelectedIndex = index + 1;
}
myTabCtrl.SelectedIndex = index;
If you don't have any way to hide the DatagridView on your form, you could simply minimize the form and then restore it back.
The problem is that there will be a fresh on the UI.

It seems, TAB, SHIFT+TAB, END keys don't always bring last column into the visible view.
The following code inside the CurrentCellChanged event handler seems to fix this issue (vb.net):
If Me.MyDataGridView.CurrentCell IsNot Nothing Then
Dim currentColumnIndex As Integer = e.MyDataGridView.CurrentCell.ColumnIndex
Dim entireRect As Rectangle = _
Me.MyDataGridView.GetColumnDisplayRectangle(currentColumnIndex, False)
Dim visiblePart As Rectangle = _
Me.MyDataGridView.GetColumnDisplayRectangle(currentColumnIndex, True)
If (visiblePart.Width < entireRect.Width) Or (entireRect.Width = 0) Then
Me.MyDataGridView.FirstDisplayedCell = Me.MyDataGridView.CurrentCell
'OR Me.MyDataGridView.FirstDisplayedScrollingColumnIndex = currentColumnIndex
End If
End If

Related

Xcode UITest scrolling to the bottom of an UITableView

I am writing an UI test case, in which I need to perform an action, and then on the current page, scroll the only UITableView to the bottom to check if specific text shows up inside the last cell in the UITableView.
Right now the only way I can think of is to scroll it using app.tables.cells.element(boundBy: 0).swipeUp(), but if there are too many cells, it doesn't scroll all the way to the bottom. And the number of cells in the UITableView is not always the same, I cannot swipe up more than once because there might be only one cell in the table.
One way you could go about this is by getting the last cell from the tableView. Then, run a while loop that scrolls and checks to see if the cell isHittable between each scroll. Once it's determined that isHittable == true, the element can then be asserted against.
https://developer.apple.com/documentation/xctest/xcuielement/1500561-ishittable
It would look something like this (Swift answer):
In your XCTestCase file, write a query to identify the table. Then, a subsequent query to identify the last cell.
let tableView = app.descendants(matching: .table).firstMatch
guard let lastCell = tableView.cells.allElementsBoundByIndex.last else { return }
Use a while loop to determine whether or not the cell isHittable/is on screen. Note: isHittable relies on the cell's userInteractionEnabled property being set to true
//Add in a count, so that the loop can escape if it's scrolled too many times
let MAX_SCROLLS = 10
var count = 0
while lastCell.isHittable == false && count < MAX_SCROLLS {
apps.swipeUp()
count += 1
}
Check the cell's text using the label property, and compare it against the expected text.
//If there is only one label within the cell
let textInLastCell = lastCell.descendants(matching: .staticText).firstMatch
XCTAssertTrue(textInLastCell.label == "Expected Text" && textInLastCell.isHittable)
Blaines answer lead me to dig a little bit more into this topic and I found a different solution that worked for me:
func testTheTest() {
let app = XCUIApplication()
app.launch()
// Opens a menu in my app which contains the table view
app.buttons["openMenu"].tap()
// Get a handle for the tableView
let listpagetableviewTable = app.tables["myTableView"]
// Get a handle for the not yet existing cell by its content text
let cell = listpagetableviewTable.staticTexts["This text is from the cell"]
// Swipe down until it is visible
while !cell.exists {
app.swipeUp()
}
// Interact with it when visible
cell.tap()
}
One thing I had to do for this in order to work is set isAccessibilityElement to true and also assign accessibilityLabel as a String to the table view so it can be queried by it within the test code.
This might not be best practice but for what I could see in my test it works very well. I don't know how it would work when the cell has no text, one might be able to reference the cell(which is not really directly referenced here) by an image view or something else. It's obviously missing the counter from Blaines answer but I left it out for simplicity reasons.

How to scroll in a Gtk::ScrolledWindow to a specific row from a Gtk::TreeView

I have a Gtk::TreeView inside a Gtk::ScrolledWindow. At one point I get a Gtk::TreeRow row. How can I know if the row is in the visible area and how can I scroll the ScrolledWindow so that the row will be visible?
L.E.: I found the sollution:
Glib::RefPtr<Gtk::TreeModel> model = pSEMQueueTreeView->get_model();
Gtk::TreeModel::Children children = model->children();
Gtk::TreeModel::Children::iterator it;
it = children.begin();
pSEMQueueTreeView->scroll_to_row(model->get_path(it));

Scroll Bar Issues Automatically Scrolling Down To The Last Control

Alright, I designed a form to fit onto the current screen size I use, with the form having a vertical scroll bar to view items further down on the form.
At the bottom of the form, I have a couple of checkboxes a user has to select before clicking the submit button.
Once the user hits the submit buttom, the user can't scroll back up to the beginning of the form. The user can scroll back up, but when they stop scroll, it scrolls to the bottom where the last checkbox was checked off.
I assume by checking this last checkbox is that's setting the focus of that control?
Any suggestions on how to fix the scrolling issue?
Keep a note of the last scroll position, and reapply it on Form_Activate
Try this:
'' Declare at form level
Private LastAutoScrollPos As System.Drawing.Point
Private Sub Form1_Activated(sender As Object, e As System.EventArgs) Handles Me.Activated
Me.AutoScrollPosition = LastAutoScrollPos
End Sub
Private Sub Form1_Scroll(sender As Object, e As System.Windows.Forms.ScrollEventArgs) Handles Me.Scroll
If e.ScrollOrientation = ScrollOrientation.VerticalScroll Then
LastAutoScrollPos = New Point(LastAutoScrollPos.X, e.NewValue)
ElseIf e.ScrollOrientation = ScrollOrientation.HorizontalScroll Then
LastAutoScrollPos = New Point(e.NewValue, LastAutoScrollPos.Y)
End If
End Sub

Change cell background color without changing focus

On a form I have 4 MSFlexGrids.
The top grid contains dynamic data, which updates once in a while.
The user can enter data in the cells of the 3 other grids.
The data which is used to fill the top grid is received via a Winsock control, processed, and then the results are written into the appropriate cells using .TextMatrix(intRow, intCol) = strData
This works fine. The data is updated flawlessly, and the user can enter his data into the other 3 grids without any problems.
The problem occurs when I want to change the background color of some cells in the top grid.
On rare occasions the received data is very important, and the background color of the corresponding cells should change color.
I change the color of the cells with the following code:
With grd
For lngRow = 1 To .Rows - 1
'default background color
lngBack = vbWhite
'check for important values
If Val(.TextMatrix(lngRow, 1)) >= lngMax Then
'important color
lngBack = &H3040FF
End If
'select whole row
.Row = lngRow
.Col = 0
.RowSel = lngRow
.ColSel = .Cols - 1
'set the background color of the selected row
.CellBackColor = lngBack
Next lngRow
End With 'grd
The problem with this is that when the user is entering data in the other 3 grids, and the background color of a row in the top grid is changed, then the focus moves to the top grid, and the user has to enter his data anew in the grid where he was working.
Is it possible to change the background color of a cell or whole row in a MSFlexGrid without moving the focus to that grid?
So far I could not find a solution to the problem itself.
I created a work around though :
I created an enum containing a value for each grid:
Public Enum ActiveGrid
enuSystem = 0
enuTel = 1
enuRLN = 2
enuRood = 3
enuData = 4
enuCircuit = 5
End Enum
Whenever a grid gets the focus I save the corresponding enum value in a form level variable.
After coloring the required cells in the first grid I return the focus to the grid which last had it.
The user is not editing in the grid itself, but in a textbox which is laid over the cell, so there is no real problem with the grid losing the focus.
When you look closely though you see the focus leave and return quickly.
For now I will accept this work around, and its minor glitches.
Maybe in the future I can come up with a better solution, or anyone else has a better suggestion?

How to retrieve the controls inside the selected item from a listbox in WP

I'm now facing the most common problem faced my many while working with listboxes. Though I found many answers the the forum, nothing seems to work for me or else i have got it wrong. .
I have created a listbox through code. Every listbox item has a stackpanel and within it two textblocks. the stackpanel has vertical orientation.The foreground of the textblocks have been set to specific colors. When an item has been selected or clicked it moves to another page and on the close of the new page it returns to the old page.
My problem is that, when a listbox item has been clicked, it does not show the selection color which is by default the phones accent color before moving to the next page. Is it because the color of the textblocks have already set while creating the listbox?
So i tried to set it the foreground of the selected item through the SelectionChanged() like this
ListBoxItem selItem = (ListBoxItem)(listboxNotes.ItemContainerGenerator.ContainerFromIndex(listboxNotes.SelectedIndex));
selItem .Foreground = (SolidColorBrush)Application.Current.Resources["PhoneAccentBrush"];
But this does not work, and i assume its cuz there is a stackpanel inside the item.
How exactly this needs to be done? Do i need to retrieve the textblocks inside the stackpanel and set the foreground?? I have not used binding here. Visual Tree Helper???
Thanks
Alfah
In general, the selected color doesn't change on lists where you're navigating.
From my experience with android, there's no 'selector' background on WP7. If you're looking for a cool UI effect that shows some action is happening, the TiltEffect is definitely recommended, and very easy to implement.
http://www.windowsphonegeek.com/articles/Silverlight-for-WP7-Toolkit-TiltEffect-in-depth
However - if you're creating an app that doesn't have immediate navigation, it is possible that you might want a 'selected' cell color / etc. I've attached an image:
https://skydrive.live.com/redir.aspx?cid=ef08824b672fb5d8&resid=EF08824B672FB5D8!366&parid=EF08824B672FB5D8!343
If you note here, the buttons are related to the selected item on the list - I.e. the user can perform 4 different actions based on the selected item, (but they must select an item first!).
internal void SelectionChanged()
{
var item = (((ListBoxItem) _view.servers.SelectedItem).Content) as StackPanel;
if (item != null)
{
for (int i = 0; i < _view.servers.Items.Count; i++)
{
var val = (((ListBoxItem) _view.servers.Items[i]).Content) as StackPanel;
var tb = val.Children[0] as TextBlock;
var tb2 = val.Children[1] as TextBlock;
if (i == _view.servers.SelectedIndex)
{
tb.Foreground = tb2.Foreground = (SolidColorBrush) App.Current.Resources["PhoneAccentBrush"];
}
else
{
tb.Foreground = tb2.Foreground = (SolidColorBrush) //regular color here, b/c all these should no longer be selected
}
}
}
}
The ListItemContainer will have it's Foreground changed automatically. To inherit this, simply don't specify a colour (or style) on your TextBlock.

Resources