Datagrid inside another datagrid - c#

I need to show a datagrid inside another datagrid. I have done this by using RowDetailsTemplate and adding a datagrid in it. But the main problem is, I need to show multiple inner grids at same time. When the selected item is changed, the inner datagrid of the previous selected item is not displayed. Any suggestions :(
I am using expander control to show/hide the details. When expander control is opened, I am changing the RowDetailstemplate's visiblity to true.
When the selected item is changed, RowDetailsTemplate of the current selected row is only being visible if I expand the expander.

You can control the visibility of the row details of each row using the DataGridRow.DetailsVisibility property.
Perhaps you also need to change DataGrid.RowDetailsVisibilityMode to another value than VisibleWhenSelected

Found the answer,
private void Expander_Expanded(object sender, RoutedEventArgs e)
{
int rowIndex = this.DataGridForEvents.SelectedIndex;
List<DataGridRow> rows = GetRows();
rows[rowIndex].DetailsVisibility = Visibility.Visible;
}
private void Expander_Collapsed(object sender, RoutedEventArgs e)
{
int rowIndex = this.DataGridForEvents.SelectedIndex;
List<DataGridRow> rows = GetRows();
rows[rowIndex].DetailsVisibility = Visibility.Collapsed;
}
public List<DataGridRow> GetRows()
{
List<DataGridRow> rows = new List<DataGridRow>();
foreach (var rowItem in this.DataGridForEvents.ItemsSource)
{
this.DataGridForEvents.ScrollIntoView(rowItem, this.DataGridForEvents.Columns.Last());
FrameworkElement el = this.DataGridForEvents.Columns.Last().GetCellContent(rowItem);
DataGridRow row = DataGridRow.GetRowContainingElement(el.Parent as FrameworkElement);
if (row != null)
rows.Add(row);
}
return rows;
}

Related

Set datasource of particular cell's combobox based on another column of particular row

private void dgGrid_CellListSelect(object sender, CellEventArgs e)
{
if (e.Cell.Column.Key == "ColumnA")
{
UltraGridRow selectedItem = ((UltraCombo)e.Cell.EditorControlResolved).SelectedRow;
if (selectedItem != null)
{
//Option A
cmbColumnB.DataSource = GetUISender<someBF>().RetrieveData(dataset).dataTable;
cmbColumnB.DataBind();
//Option B
//((UltraCombo)e.Cell.Row.Cells["ChipSetID"].EditorControlResolved).DataSource = GetUISender<someBF>().RetrieveData(dataset).dataTable;
}
}
}
There is a button that allow the datagrid to add new row.
This datagrid have 2 columns and both columns are UltraCombo. ColumnB combobox's dataSource will based on ColumnA. Based on the above code, it works if the datagrid only have 1 row, but once user add another row, both row's ColumnB will be sharing the same DataSource.
How to make sure ColumnB's DataSource stay independently without affecting other rows? It's very obvious that this happened because every row are sharing the same component which is cmbColumnB but I'm not sure on how to remove the reference
I've found the solution which is everytime create a new UltraCombo and bind it to the particular cell's EditorControl
private void dgGrid_CellListSelect(object sender, CellEventArgs e)
{
if (e.Cell.Column.Key == "ColumnA")
{
UltraGridRow selectedItem = ((UltraCombo)e.Cell.EditorControlResolved).SelectedRow;
if (selectedItem != null)
{
UltraCombo cmbValue = new UltraCombo();
cmbValue.LimitToList = true;
cmbValue.DropDownStyle = UltraComboStyle.DropDownList;
cmbValue.DataSource = GetUISender<someBF>().RetrieveData(dataset).dataTable;
cmbValue.ValueMember = someDS.someDT.someColumnIDColumn.ColumnName;
cmbValue.DisplayMember = someDS.someDT.someColumnDescriptionColumn.ColumnName;
cmbValue.BindingContext = someDg.BindingContext;
cmbValue.DataBind();
e.Cell.Row.Cells["ColumnB"].EditorControl = cmbValue;
e.Cell.Row.Cells["ColumnB"].Style = Infragistics.Win.UltraWinGrid.ColumnStyle.DropDownList;
}
}
}

How to get a Telerik Multi column combo box value which is a column in rad grid view?

I want to get the first element of telerik multi combo box which is a column of a telerik grid view
when user selects a row i want to get the first element of that row and pass it to my DB
i've done some thing but i geuss it's not enough
if (Ref_MultiColumnComboBox.MultiColumnComboBoxElement.SelectedIndex >= 0)
{
var tr = Ref_MultiColumnComboBox.MultiColumnComboBoxElement
.EditorControl.Rows[Ref_MultiColumnComboBox.MultiColumnComboBoxElement.SelectedIndex]
.Cells["Id"].Value.ToString();
MessageBox.Show("m= {0}" + " // " + tr);
}
else
{
MessageBox.Show("", "Error");
}
the problem is that when user selects some row or doesn't selectedindex is allways -1
Here is one way to do it for RadMultiColumnComboBox control:
void radMultiColumnComboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
GridViewDataRowInfo selectedRow = (GridViewDataRowInfo)radMultiColumnComboBox1.SelectedItem;
Console.WriteLine(selectedRow.Cells["Id"].Value.ToString());
}
The SelectedItem provides a reference to the selected row in the inner grid, from where you can access its cells and values.
If GridViewMultiComboBoxColumn is used, then you can use either the ValueChanged event, or the CellValueChangned events to get the row of the currently selected item:
void radGridView1_CellValueChanged(object sender, GridViewCellEventArgs e)
{
RadMultiColumnComboBoxElement mccbEditor = (RadMultiColumnComboBoxElement)e.ActiveEditor;
GridViewDataRowInfo selectedRow = (GridViewDataRowInfo)mccbEditor.SelectedItem;
Console.WriteLine(selectedRow.Cells["Id"].Value.ToString());
}
void radGridView1_ValueChanged(object sender, EventArgs e)
{
RadMultiColumnComboBoxElement mccbEditor = (RadMultiColumnComboBoxElement)radGridView1.ActiveEditor;
GridViewDataRowInfo selectedRow = (GridViewDataRowInfo)mccbEditor.SelectedItem;
Console.WriteLine(selectedRow.Cells["Id"].Value.ToString());
}

AllowDrop on a DataGrid Row based on mouse position

I am wondering, if I can use an AllowDrop on a datagrid row, instead of the DataGrid itself.
I'll explain :
I can do allowDrop on datagrid, and then, I tried to identified the row, where I drop my item.
The thing is, it keep the row selected before I drop the item. Because when I drag an item on a row in the datagrid, it doesn't do the select event.
So, is there a way to, either put AllowDrop on a row, so I can identify it more easily, or either way, identify the good row, with the position of the mouse, when I drop the item.
edit : so, after putting AllowDrop on a Row, this still doesn't work. The problem is, to be able to selected a Row, when I drop an item on it. Is this possible?
Can I, get the Selected row, based on the mouse position (or the drop item position)?
Thanks for your help.
Add a handler to the DataGrid for the DataGrid.LoadingRow event:
The DataGrid_LoadingRow event will be passed DataGridRowEventArgs.
The DataGridRowEventArgs contains the row that is being loading.
Example:
private void MyDataGrid_LoadingRow(object sender, DataGridRowEventArgs e)
{
e.Row.AllowDrop = true;
}
How to get the row under the mouse:
private void DataGrid_OnDrop(object sender, DragEventArgs e)
{
DataGridRow dataGridRow = null;
var point = e.GetPosition(null);
var elements = VisualTreeHelper.FindElementsInHostCoordinates(point, theDataGrid);
if (elements != null && elements.Count() > 0)
{
var rowQuery = from gridRow in elements where gridRow is DataGridRow select gridRow as DataGridRow;
dataGridRow = rowQuery.FirstOrDefault();
}
}

C# WPF ListView with GridView - add/remove columns context menu

I'm trying to add a context menu to a ListView (using GridView) to toggle column visibility. It's a simple menu - it just has a list of all the available columns, and if the column name is checked, that column should be visible.
My ListView is displayed with a GridView. The GridViewColumnHeader for each column has a Name property and Header property that match with a ContextMenu MenuItem with the same Name and Header values. My problem is that I can't figure out how to select a GridViewColumn by its GridViewColumnHeader's name without iterating through all the columns.
I can select a column by index, but that won't work since the column index changes if the columns are reordered by the user.
Is there a way to select a column by header data? I'm thinking something like this:
MenuItem m = e.Source as MenuItem;
GridView gv = (GridView)list.View;
GridViewColumn gvc = gv.Columns[m.Name];
//code to make width 0 or Auto goes here...
Looks like there is no built in method for this.
You can use LINQ expression:
var col = gv.Columns.FirstOrDefault(it => it.Header == "name");
but it will iterate through the columns inside. I believe iterating will be pretty fast.
The other way to avoid iterating completely is to subscribe on CollectionChanged event and save mapping between column header and column. But this is tricky way.
private Dictionary<object, GridViewColumn> _columns = new Dictionary<object, GridViewColumn>();
public MainWindow()
{
InitializeComponent();
gv.Columns.CollectionChanged += Columns_CollectionChanged;
}
private void Columns_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if((e.Action==NotifyCollectionChangedAction.Remove
|| e.Action==NotifyCollectionChangedAction.Replace)
&& e.OldItems!=null)
{
foreach(GridViewColumn oldItem in e.OldItems)
{
if(_columns.ContainsKey(oldItem.Header)) _columns.Remove((oldItem.Header));
}
}
if(e.NewItems!=null)
{
foreach(GridViewColumn newItem in e.NewItems)
{
_columns[newItem.Header] = newItem;
}
}
}
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
try
{
gv.Columns.CollectionChanged -= Columns_CollectionChanged;
}
catch { }
}
private GridViewColumn GetColumn(string header)
{
GridViewColumn column = null;
_columns.TryGetValue(header, out column);
return column;
}

C# - Datagridview columns

I have a DataGridView in a WinForm. I fill the DataGridView from a database table. I was wondering if there is any way to program my DataGridView so that I can choose which columns I want the gridview to show at runtime?
The simple answer is "yes".
In the first instance you need to set the AutoGenerateColumns property of the DataGridView to false then you can control which columns get displayed.
In the past I've created a context menu for the DGV:
ContextMenu = new ContextMenu();
foreach (var column in this.dataGridView.Columns)
{
this.AddContextMenuItem(ContextMenu, column.Name, column.Visible);
}
private void AddContextMenuItem(ContextMenu contextMenu,
string columnName,
bool visible)
{
var menuItem = new MenuItem(columnName,
new EventHandler(this.ContextMenu_onClick)) { Checked = visible };
contextMenu.MenuItems.Add(menuItem);
}
Then when the the menu option is toggled change the Visible property of the column.
private void ContextMenu_onClick(object sender, EventArgs e)
{
var clicked = sender as MenuItem;
if (clicked != null)
{
// Update the state of the context menu
clicked.Checked = !clicked.Checked;
// Update the visibity of this column
this.dataGridView.Columns[clicked.Text].Visible = clicked.Checked;
}
}
Use the DataGridView.AutoGenerateColumns property--set to false. Explicitly configure the columns you want, and you're good to go.

Categories

Resources