Can we render two UI element at same grid position in SelectionChanged event of a combo box.
The exact problem is i have grid and inside the grid there are two rows the first row will always show me a ComboBox(of which i was talking about line before) on selecting
different item will render different UI elemnts at same position in the second row of the grid.
So i tried to do the rendering of the UI element in the SelectionChanged event of the Combo.
But the problem happening is when i select the first element then it is displayed properly but when i try to select the second UI element to be rendered at same position on Combo selection change then it gives a warning
"the value is not within the expected range." at Line : "bigGrid.Children.Add(ck);"
My code to do this is:
Grid childGrid = createChildGrid();
Grid ck = new Grid(); //This ck will contain ComboBox at row zero and UI element at second row
ck.RowDefinitions.Add(new RowDefinition());
ck.RowDefinitions.Add(new RowDefinition());
int loopCount = 0; //This variable will help in changing the row index
if (loopCount == 0)
{
ComboBox cmb = new ComboBox();
//Here i add items in Combo:
foreach(string ccyp in attributeName)
{
if (ccyp != null)
cmb.Items.Add(ccyp);
}
cmb.SelectionChanged += (o, e) =>
{
txtblkName.Text = cmb.SelectedValue.ToString();
ck = generateUIElementCorrespondingTotxtLabelNameObtainedOnComboSelection(txtblkName.Text); //this function will return a grid containing the selected UI elemnt from combo box.
Grid.SetRow(ck, loopCount);
bigGrid.Children.Add(ck); //**THIS LINE GIVE EXCEPTION: "the value is not within the expected range."**
};
}
Grid.SetColumn(cmb, 1);
childGrid.Children.Add(cmb);
Grid.SetRow(childGrid, loopCount);
bigGrid.Children.Add(childGrid);
loopCount++;// I incrtease loop count so that on selection changed event of combo UI will be displayed on second row loopcount=1
EDIT: On debugging i get :The result of break point is : loopcount=1 (for rendering of combo item in second row)this " Grid.SetRow(ck, loopCount); bigGrid.Children.Add(ck);" and for combo box display loopcount= 0 (i mean here : "Grid.SetRow(childGrid, loopCount); bigGrid.Children.Add(childGrid); loopCount++;")
From question Silverlight: Value does not fall within the expected range exception
'This error can be caused when there are two elements being added with the same name.' What identifiers are added to the combo boxes?
If this is the problem, as suggested in the linked question, you could add a unique identifier to each combo box.
Related
The goal is to copy the selected cell data out of a selected row.
I'm doing this by catching the CopyingRowClipBoardContent event inside my datagrid and redirecting it to this code:
var currentCell = e.ClipboardRowContent[VwrGrid.CurrentCell.Column.DisplayIndex];
e.ClipboardRowContent.Clear();
e.ClipboardRowContent.Add(currentCell);
This works perfectly! the only issue, is that if some of the columns are hidden, DisplayIndex reads improperly.
So if we have Item 1, Item 2, and Item 3.
If all are showing and I selected item3 and copy it, I get the cell value in Item 3.
The problem is, If Item 2 is collapsed/not shown, then copying Item 3 will tell you you're trying to copy out of bounds. because it's counted displayIndex , 3 from the left, and only two were shown. so it's moved outside of the table
For WPF Datagrid, try this:
// The clipboard row works only for visible cells
// To obtain the data column use the columnIndex and then map that to the Columns collection
int columnIndex = dataGrid.CurrentCell.Column.DisplayIndex;
var column = dataGrid.Columns[columnIndex];
// Now get the needed column
var cellContent = e.ClipboardRowContent.Where(i => i.Column == column).First();
e.ClipboardRowContent.Clear();
e.ClipboardRowContent.Add(cellContent);
For Winforms:
Use .Index instead. .DisplayIndex applies only to visible columns.
Because this is WPF and I can't simply use an index, I just iterated through the columns and counter the number of columns that had their visibility set to collapsed up to the column we were attempting to grab the displayindex for. Then subtracted that number from the displayIndex.
private void DataGrid_CopyingRowClipboardContent(object sender, DataGridRowClipboardEventArgs e)
{
//because we need to use displayindex, we need to check how many collapsed columns there are before our column, and adjust our display index accordingly
int invisibleCols = 0;
foreach(DataGridColumn col in VwrGrid.Columns)
{
if (col.Visibility == Visibility.Collapsed)
invisibleCols++;
if (col.Header.ToString() == VwrGrid.CurrentCell.Column.Header.ToString()) break;
}
try
{
var currentCell = e.ClipboardRowContent[VwrGrid.CurrentCell.Column.DisplayIndex - invisibleCols];
e.ClipboardRowContent.Clear();
e.ClipboardRowContent.Add(currentCell);
}
catch
{
}
}
I am trying to obtain DataGridRow from my DataGrid based on index. I am using following code:
public DataGridRow GetGridRow(int index)
{
DataGridRow row = (DataGridRow)DG_Statement.ItemContainerGenerator.ContainerFromIndex(index);
if (row == null)
{
// May be virtualized, bring into view and try again.
DG_Statement.UpdateLayout();
DG_Statement.ScrollIntoView(DG_Statement.Items[index]);
row = (DataGridRow)DG_Statement.ItemContainerGenerator.ContainerFromIndex(index);
}
return row;
}
Ref Link - Get row in datagrid
But unfortunately its returning a null object of DataGridRow.
If I check the Items[] property of my grid I could see 13 items.
Need suggestion on how to obtain the Grid Row as I want to change color of top 2 and bottom 2 rows of my data grid.
Any help is appreciated. Thanks!!
Adding Screenshot of DataGrid Items
Important Update
If I call GetGridRow() from the SelectedIndexChanged Event of the Grid it works flawlessly.
On the other hand, if I call it after I construct the object of the page on which my grid is displayed it returns row object as NULL.
So if its in the code behind. You can just get the selected index of the DataGrid. I've named the datagrid dataGrid as an example.
var rowIndex = dataGrid.SelectedIndex;
var row = (DataGridRow)dataGrid.ItemContainerGenerator.ContainerFromIndex(selectedIndex);
Check to make sure the index you're passing in is actually within bounds.
I have a function for setting items in a combobox and one item is to be set by default like
--SELECT LIST--
public void SetOperationDropDown()
{
int? cbSelectedValue = null;
if(cmbOperations.Items.Count == 0)
{
//This is for adding four operations with value in operation dropdown
cmbOperations.Items.Insert(0, "PrimaryKeyTables");
cmbOperations.Items.Insert(1, "NonPrimaryKeyTables");
cmbOperations.Items.Insert(2, "ForeignKeyTables");
cmbOperations.Items.Insert(3, "NonForeignKeyTables");
cmbOperations.Items.Insert(4, "UPPERCASEDTables");
cmbOperations.Items.Insert(5, "lowercasedtables");
//ByDefault the selected text in the cmbOperations will be -SELECT OPERATIONS-.
cmbOperations.Text = "-SELECT OPERATIONS-";
}
else
{
if(!string.IsNullOrEmpty("cmbOperations.SelectedValue"))
{
cbSelectedValue = Convert.ToInt32(cmbOperations.SelectedValue);
}
}
//Load the combo box cmbOperations again
if(cbSelectedValue != null)
{
cmbOperations.SelectedValue = cbSelectedValue.ToString();
}
}
Can anyone suggest a way to do this?
I've rewritten this answer to clarify some stuff.
First, the "default" text must be added as combo item as well.
Usage of combo.Text property just adds descriptive text to combobox which is "lost" first time user do something with a control.
If you like to permanently have "default" text in your combo, you must add it as an combobox item.
By the code you provided, just modify the
cmbOperations.Text = "-SELECT OPERATIONS-"; to
cmbOperations.Items.Insert(0, "-SELECT OPERATIONS-");
Note that this way you add the item "-SELECT OPERANDS-" to the 0th (read first) position in the list.
Also make sure that all your following items are increased by 1, because they are now moved by one space down in list.
Finally, put cboOperations.SelectedIndex = 0; line at the end of code. By doing so, you're telling combobox to display your "default" item initially when the form (or control) loads.
One more thing. I'm not pretty sure what do you want to achieve with the code beyond setting combo items, but if you like to check what user selected use cboOperations.SelectedIndex property which contains currently selected item in combo. You can add simple if(cboOperations.SelectedIndex == someIntValue){...}
The rest is your program logic ;)
I'm creating a dynamic combo box and adding to a form. I'm trying to fill the combo box with a DataSource from an ArrayList and then selecting an item in the combo box based off a value from a property.
Problem is, the combo box items don't get bound until after the Form_Load event has finished and the form is visible. So the combo box is empty when I try to set the selected index of the combo box. See code for what I'm doing in detail, and refer to comments in code:
Dim cboValues As New ComboBox
cboValues.Width = fieldControlWidth
cboValues.DropDownStyle = ComboBoxStyle.DropDownList
cboValues.Name = "cboResult"
For Each d As SystemTaskResult In [Enum].GetValues(GetType(SystemTaskResult))
Dim cv As New ComboBoxDisplayValue(d.ToString, d)
arrValues.Add(cv)
Next
cboValues.DataSource = arrValues
cboValues.DisplayMember = "Display"
cboValues.ValueMember = "Value"
Dim val As SystemTaskResult = DirectCast(p.GetValue(Me.Task, Nothing), SystemTaskResult)
'Was trying to get this to work, but commented out to try the below
'cboValues.SelectedIndex = cboValues.Items.IndexOf(New ComboBoxDisplayValue(val.ToString, val))
'Then this doesn't work because the combo box hasn't updated it's DataSource yet, which is probably the reason for the above not working as well.
For i = 0 To cboValues.Items.Count - 1
cboValues.SelectedIndex = i
If cboValues.SelectedValue = val Then
Exit For
End If
Next
holdPanel.Controls.Add(cboValues)
How to select the right selected index for combo box without a hack (Load timer or something stupid like that)?
Try Form.Shown. See :
How do I execute code AFTER a form has loaded?
I have one listview whith several columns.
I want to fill this listview in a vertical form
column to column.
Sorry, but this is not (easily) possible.
A ListView has a list of ListViewItems, where each one has a List of ListViewSubItems (and to make it a little more complex at the first spot, the first ListViewSubItem is the same as the ListViewItem itself).
So if you like to fill up a ListView column by column you first have to add the ListViewItems to the ListView for all the values you want in the first column.
Afterwards you iterate through the ListView.Items and call on every ListViewItem.Subitems.Add to fill up the next column. This must be done for each column you like to fill.
If you like to fill in the column values in another order then from left to right, you should take a look into the DisplayIndex of the ColumnHeader within the ListView.Columns.
Some example code:
// Some values
var someValues = Enumerable.Range(1, 10);
// Fill up the first column
foreach (var item in someValues)
{
listView.Items.Add("0." + item);
}
// Run for each column in the listView (the first is already filled up)
foreach (ColumnHeader column in listView.Columns.Cast<ColumnHeader>().Skip(1))
{
// Get the value and the index for which row the value should be
foreach (var item in someValues.Select((Value, Index) => new { Value, Index }))
{
// Add the value to the given row, thous leading to be added as new column
listView.Items[item.Index].SubItems.Add(column.Index + "." + item.Value);
}
}