Dynamically generated FlowLayoutPanel, has different output - winforms

I'm trying to dynamically generate 2 FlowLayoutPanels with a couple of buttons.
private void DrawButtons() {
tlpButtons.Controls.Clear();
foreach (var type in Globals.ThisAddIn.TicketTypes.OrderBy(x => x.Name)) {
tlpButtons.Controls.Add(new Label() { Text = type.Name, Dock = DockStyle.Fill });
var container = new FlowLayoutPanel() { Dock = DockStyle.Fill, AutoSize = true, AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowOnly, BackColor = Color.Yellow, FlowDirection = FlowDirection.LeftToRight };
foreach (var skill in Globals.ThisAddIn.Skills.OrderBy(x => x.Name)) {
container.Controls.Add(new Button() { Text = skill.Name });
MessageBox.Show(tlpButtons.RowCount.ToString());
}
tlpButtons.Controls.Add(container);
}
}
This is what it outputs:
Let me explain what you're seeing.
I have TableLayoutPanel tlpOuter (pink) with 1 column (100%) and 2 rows. Row 1: AutoSize, Row 2: 100%
In the first row I have another TableLayoutPanel tplButtons (orange) with 1 column (100%) and 1 row (AutoSize, GrowStyle: Rows)
Now I can't figure out why the 2nd FlowLayoutPanel (yellow) is so large. It shouldn't be. It is exactly the same as the first panel (it's in a foreach) and yet, it adds all this whitespace (yellowspace).
What I found, when debugging line-by-line, is that the second panel grows as the buttons are added (as if it thinks they get a new line instead being placed side-side if it can) while it does not do that while adding the buttons to the first panel.
UPDATE:
So I removed the docking from the flowLayoutPanels and I can now see the problem is actually the TableLayoutPanel tlpButtons!
From what I can gather, it is sizing the Table as if the controls inside had no docking. Look:
So the question remains, why does this TableLayoutPanel not account for the docking of the FLP's?

Related

Scroll to selection in Angular ui-grid (not ng-grid)

For my Angular JS grid work, I'm using ui-grid rather than ng-grid as ui-grid is meant to be the new version which is purer Angular.
I've got a grid that I'm populating with a http response, and I'm able to select a row (based on finding the record matching a $scope variable value) using the api.selection.selectRow method call.
What I need to do next is scroll the grid to that record.
There's an existing stack overflow question along the same lines that is for ng-grid and the answer to that refers to undocumented features which are not present in ui-grid so I can't use that approach.
The closest I've got is finding $scope.gridApi.grid to get a reference to the actual grid itself but looking through the properties and methods in the Chrome debugger doesn't show anything that sounds like it could work.
You can use the cellNav plugin. You should already have a reference to your row entity from the selection. The documentation is here.
gridApi.cellNav.scrollTo(grid, $scope, rowEntity, null);
I managed to hack together something that works pretty well but it's a bit dodgy and could probably be cleaner with a bit more Angular/jquery understanding.
I used the browser dom explorer to find that the scrollbars have a css class that we can detect to find them and then set the scroll properties on them to have the grid scroll (the grid and scrollbars are separate divs but their properties are bound so changing one updates the other).
It doesn't completely work for scrolling to the last row of the grid. This could be a timing issue, I've noticed when using breakpoints that the grid comes on screen a little larger and then shrinks down to it's final size. This could be messing with the scrolling values.
The first loop finds the height of the grid by adding up the rows, and the y position of the row for my data object (project), then we find the scrollbar and set it's scrollTop, trying to centre the row on screen without going out of bounds.
var grid = $scope.projectsGridApi.grid;
// var row = grid.rowHashMap.get(project.$$hashKey);
var found = false;
var y = 0;
var totalY = 0;
var rowHeight = 0;
for (var rowIdx in grid.rows)
{
var row = grid.rows[rowIdx];
if (row.entity.$$hashKey == project.$$hashKey)
{
found = true;
rowHeight = row.height;
}
if (!found)
{
y += row.height;
}
totalY += row.height;
}
// now find the scroll bar div and set it's scroll-top
// (todo: checking if we're at the end of the list - setting scrollTop > max means it doesn't work properly
var grid = $scope.projectsGridApi.grid;
// annoyingly this is nastily coded to find the scrollbar and isn't completely right
// I think the grid is a little taller when this is called, then shrinks
// which affects what the maximum is (so we might not always be able to put the selected item on screen if it is the last one).
var holderDiv = $('#projectsGridHolder');
if (holderDiv)
{
var scrollBarDivs = holderDiv.find('.ui-grid-native-scrollbar');
if (scrollBarDivs)
{
for (var scrollBarDivIdx in scrollBarDivs)
{
var scrollBarDiv = scrollBarDivs[scrollBarDivIdx];
var scrollBarDivClass = scrollBarDiv.className;
if (scrollBarDivClass)
{
if (scrollBarDivClass.indexOf('vertical') != -1)
{
var scrollHeight = scrollBarDiv.scrollHeight;
var clientHeight = scrollBarDiv.clientHeight;
if (rowHeight > 0)
{
y -= (clientHeight - rowHeight) / 2; // center on screen be scrolling slightly higher up
}
if (y < 0) y = 0;
else if (y > totalY - clientHeight) y = totalY - clientHeight;
scrollBarDiv.scrollTop = y;
}
}
}
}
}

How can I exchange the Extjs panel contents?

In my application there are two panels -A and B.
I am using "border" layout, the panel A is in center region and panel B is in south region which have height 200.
The "panel A" have lot of items like grid, toolbar etc. also "panel B" have some items.
My question is, How can I exchange the contents of A to B and B to A.
Note: I am using "Extjs 3.2"
Regards,
Mohammed Shafeek
Panels in center and south region of border layout have to be wrapped by container component. Then you can easily get content of each container, clear the container and add to it content from second container.
So function for switch panels should looks like this:
function switchPanels() {
southContainer = Ext.getCmp('southContainer');
centerContainer = Ext.getCmp('centerContainer');
southContainerItems = southContainer.items.getRange();
centerContainerItems = centerContainer.items.getRange();
southContainer.removeAll(false);
centerContainer.removeAll(false);
for (var i = 0; i < southContainerItems.length; i++) {
centerContainer.add(southContainerItems[i]);
};
for (var i = 0; i < centerContainerItems.length; i++) {
southContainer.add(centerContainerItems[i]);
};
centerContainer.doLayout();
southContainer.doLayout();
}
For complete live example look at this fiddle: https://fiddle.sencha.com/#fiddle/2iv

silverlight build a datagrid in the code behind

Is it possible in a Silverlight DataGrid to have a column that has rows with different types of controls? For instance the first two rows of the column should be text, the next two rows would have buttons and then the next 6 rows would have Checkboxes. I need to build it in the code behind also. Any help would be appreciated.
Maybe the code below code gives you the idea.
foreach (var item in ItemList)
{
//Row definition and column definitions are similar
LayoutRoot.RowDefinitions.Add(new RowDefinition()
{ Height = GridLength.Auto});
HelloObject hl=new HelloPObject();
//Attached property imeplemantation
Grid.SetRow(hl,Layout2.RowDefinitions.Count);
//You may add any UIElement as Children
LayoutRoot.Children.Add(hl);
}
EDIT: Sorry I didn't realize datagrid.
Ok its possible for datagrid also ,
AFAIK Telerik's radgridview gives you the index of row .But you can manage by yourself.
Beside this when you hit grids ordering this order may be lost depending on your sortingmemberpath of column. But you can switch your CellTemplate depending a property in DataGrid's ItemsSource elements.
DataGrid grid = new DataGrid();
int rowNdx = 0;
grid.LoadingRow += (s, a) =>
{
DataGridCell cell = myList.Columns[0].GetCellContent(a.Row).Parent as DataGridCell;
switch (rowNdx)
{
case 0:
cell.Content = new TextBlock() { Text= "Click" };
break;
default:
cell.Content = new Button() { Content = "Click" };
break;
}
rowNdx++;
};

Datagridview Column width

I have problem related to datagridview in Winform.
I have a list of table names in my left panel. When I click on Table I show the table content in right panel. I am showing data in a datagridview by fetching data and assigning datasource to dgv.
I am setting following property to dgv.
dgTemp.Dock = DockStyle.Fill;
dgTemp.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;
dgTemp.AutoSize = true;
dgTemp.DefaultCellStyle.WrapMode = DataGridViewTriState.True;
dgTemp.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.AllCells;
dgTemp.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.DisableResizing;
dgTemp.ReadOnly = true;
dgTemp.AutoGenerateColumns = true;
dgTemp.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
dgTemp.AllowUserToAddRows = false;
My problem is there can be any number of columns in Datasource I am assigning to dgv. So if there are very few number of columns (say 1 or 2) the dgv size stands very small and the empty space on right side give very ugly look.
I can't use auto autosizecolumnmode to fill since when there is more columns all columns get shrink and expanding columns dont give me Scroll at bottom
so My requirement is
All space in datagridview should be filled. (should cover all area)
When there is more column, there should appear scroll, so it give better look
are there any events or properties which I can use ??
Thanks in anticipation.
Try this :
dgTemp.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
Update :
dataGridView1.FirstDisplayedScrollingRowIndex = 5; //use 5 because you want to start from 5
//you can have a horizontal scroll bar with this code :
dataGridView1.FirstDisplayedScrollingColumnIndex = 10; //you can choose every column you wanna start with that column
Update 2 :
int rows = dataGridView1.Rows.Count;
int columns = dataGridView1.Columns.Count;
if (rows < 5 && columns < 10)
{
dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
}
else
{
dataGridView1.FirstDisplayedScrollingRowIndex = 5; //use 5 because you want to start from 5
//you can have a horizontal scroll bar with this code :
dataGridView1.FirstDisplayedScrollingColumnIndex = 10; //you can choose every column you wanna start with that column
}

select a datagrid cell that contains a given value in wpf

I bound a DataTable to a datagrid in wpf. The first column has unique values. Now I would like to autoselect a cell in the second column whose first column cell has the given value. How should I achieve that? For example,here is my datagrid:
Name | Age
cat | 2
dog | 3
When user input 'dog', I will need the '3' to be selected.
I tried the method show here:
How to select a row or a cell in WPF DataGrid programmatically?
However, I cannot figure out the displaying row number. Even though I know the row number of the dataTable, the display number can be different since I allow users to sort the table.Thanks a lot.
Set your grid's SelectionUnit property to "Cell", and assuming you feed the DataGrid with the table's DefaultView:
private void button1_Click(object sender, RoutedEventArgs e)
{
// Search for the source-row.
var Element = MyDataTable.AsEnumerable()
.FirstOrDefault(x => x.Field<string>("Name") == "horse");
if (Element == null) return;
// Found the row number in the DataGrid
var RowOnGrid = MyGrid.Items.OfType<DataRowView>()
.Select((a, Index) => new { data=a.Row, index = Index })
.Where(x=> x.data == Element)
.Select(x => x.index)
.FirstOrDefault();
// Assuming the desired column is the second one.
MyGrid.SelectedCells.Clear();
MyGrid.SelectedCells.Add(new DataGridCellInfo(MyGrid.Items[RowOnGrid], MyGrid.Columns[1]));
}
It should work even if you re-sort the rows.

Resources