I have a loaded event of combobox placed in each datagrid row.Event is as following.
private void show(object sender, RoutedEventArgs e)
{
ComboBox cmb = null;
if (sender is ComboBox)
{
cmb = (sender as ComboBox);
}
for (var vis = sender as Visual; vis != null; vis = VisualTreeHelper.GetParent(vis) as Visual)
if (vis is DataGridRow)
{
var row = (DataGridRow)vis;
break;
}
cmb.items.add("1","2","3");
}
Now I want to call it at winload or any button event as method. how it is possible.
I am sorry, but what you're saying is not possible. You cannot find a combobox loaded event from somewhere, since it is not under your control.
It is fired internally when the combobox is loaded. Hence you get the sender as combobox.
If your purpose is simply adding values to the combobox consider binding the data template of your data grid to some source and bind the combobox source to some collection. Doing that will add the items initially to the combobox while the application is loaded and you could change the values accordingly while the application is running by changing the bound sources of combobox in the datatemplate.
Related
I'm trying to call a method which fills a table with data according to the ListBoxItem that has been selected.
// Setting the ListBoxItems
myListBox.ItemsSource = list;
// Calling the method when the ListBox's selection changes
myListBox.SelectionChanged += LbItem_Select;
The above snippet can't work because the LbItem_Select event handler doesn't get as a parameter the item that is currently selected.
This is the event handler:
private void LbItem_Select(object sender, RoutedEventArgs e)
{
var lbItem = sender as ListBoxItem;
lbItemContent = lbitem.Content.ToString();
// fill the table according to the value of lbItemContent
}
How could I achieve this?
When you work with events, sender is the object related to the event. myListBox.SelectionChanged is an event of the ListBox. So sender is the ListBox, not the item. Try with this:
private void LbItem_Select(object sender, RoutedEventArgs e)
{
var listBox = sender as ListBox;
// Or use myListBox directly if you have the ListBox available here
var item = listBox.SelectedItem;
// Do whatever with the item
}
the event is triggered when the Form with the DataGridView is initialized, when the column headers texts are placed. So the function handling the event runs at start-up as many time as there are columns. How can I stop that and have it triggered only after the user made some changes in the datagrid?
Added:
It seems that changing from CellValueChanged to CellEndEdit does the trick.
Have you tried using the SelectionChanged property of the datagrid, triggering an event when the content changes?
<Grid>
<DataGrid> Name="TestDataGrid" SelectionChanged="DataGrid_EventName" />
</Grid>
Within the Code-Behind, the event will be captured:
private void DataGrid_EventName(object sender, SelectionChangedEventArgs e)
{
//Conduct work here
}
Edit: I'm quite sure that you will still need to initialize the DataGrid.
For example, you can use this event to extract the row-specific information from within the DataGrid:
private void DataGrid_EventName(object sender, SelectionChangedEventArgs e)
{
DataGrid _dataGrid = (DataGrid)sender;
DataRowView selectedRow = _dataGrid.SelectedItem as DataRowView;
if (selectedRow != null)
{
RowItemList = new List<string>(); //List declared outside of this method...
//add row information to the list
RowItemList.Add(selectedRow.ToString());
//or, get column-specific information
string ColmnEntry = selectedRow[ColumnName].ToString();
}
}
In my C# WPF application (.NET 4.0) I have a DataGrid dynamically filled from code including a DataGridComboBoxColumn:
public static DataGridComboBoxColumn getCboCol(string colName, Binding textBinding)
{
List<string> statusItemsList = new StatusList();
DataGridComboBoxColumn cboColumn = new DataGridComboBoxColumn();
cboColumn.Header = colName;
cboColumn.SelectedItemBinding = textBinding;
cboColumn.ItemsSource = statusItemsList;
return cboColumn;
}
Using the BeginningEdit event different checks are performed.
If the checks return okay, I want to expand the combobox directly, otherwise edit mode is cancelled:
void dataGrid_BeginningEdit(object sender, DataGridBeginningEditEventArgs e)
{
...
if(notOK)
e.Cancel;
else {
DataGridComboBoxColumn dgCboCol = (DataGridComboBoxColumn)e.Column;
// expand dgCboCol
}
...
}
Questions: How to expand the combobox programmatically? Is BeginningEdit event the right place to do that?
Answer:
void dataGrid_PreparingCellForEdit(object sender, DataGridPreparingCellForEditEventArgs e)
{
if (e.EditingElement.GetType().Equals(typeof(ComboBox)))
{
ComboBox box = (ComboBox)e.EditingElement;
box.IsDropDownOpen = true;
}
}
Take a look at this
Try setting edit mode on the grid to a single click and then use the CellClick event to obtain the comboBox and expand it.
dataGrid.BeginEdit(true);
ComboBox comboBox = (ComboBox)dataGrid.EditingControl;
comboBox.IsDropDownOpen = true;
From DataGridBeginningEditEventArgs, you could access the generated element for the cell about to be edited like this:
var contentComboBox = e.Column.GetCellContent(e.Row) as ComboBox;
However, I'm not sure that this will get the actual ComboBox you need. DataGrids can generate two different elements for each cell, depending on whether they are in edit mode (read-only and read-write elements). Since BeginningEdit happens just before entering edit mode, this will get the read-only element.
The better event to handle this in would probably be PreparingCellForEdit, which will fire after BeginEdit is actually called on the data item (in other words, if BeginningEdit was not canceled). In that event, you can access the element directly through the EditingElement property.
I have a DataGrid created in XAML in a C# project. I've added a context menu to the rows. Basically when the user clicks directly on the cell it should open the relevant item in the current window, which is implemented on the SelectionChanged event.
However if the user right clicks a row it should show the the context menu without selecting the row, so that the user can select an item in the context menu to open the relevant item in a new window. So they can look at both the already selected item and the new item at once, but as the right click selects the row, the user see the newly selected item in the current window and the new window.
How can I stop the right click action to show the context menu from selecting the cell?
For my solution, I have to overwrite the following two event handlers (i.e., PreviewMouseRightButtonDown and PreviewMouseRightButtonUp). Plus, not sure why data-binding for the ItemsSource does not work, so that I have to bind it manually.
private void ResultDataGrid_PreviewMouseRightButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
if (sender is DataGrid dg)
{
if (this.DataContext is PipelineStepResultViewModel dataContext
&& dataContext.DatagridMenuItems != null)
{
dg.ContextMenu.ItemsSource = dataContext.DatagridMenuItems;
}
}
e.Handled = true;
}
private void ResultDataGrid_PreviewMouseRightButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
if (sender is DataGrid dg && dg.ContextMenu.ItemsSource != null)
{
ResultDataGrid.ContextMenu.IsOpen = true;
}
e.Handled = true;
}
I've a very trivial requirement which makes me go nuts. I've a DataGridView in windows forms application. This contains one databound ComboBox Column. I'm using DisplayMember and ValueMember properties of that combobox.
Now my requirement is ComboBox should show the list of DisplayMembers in drop down list but when user selects one item from it, I should display the part of that DisplayMember in the combobox cell visible to the user. For example.
My display member list looks as below:
"Cust1 - Customer 1"
"Cust2 - Customer 2"
"Cust3 - Customer 3"
and when user selects any one of them from the above list (Say user selected 'Cust2 - Customer 2') then I need to display the value in the combobox column cell as only "Cust2" instead of complete DisplayMember text.
This DisplayMember list is a combination of two fields from the datasource bound to it i.e. First part points to CustomerCode field and second part points Customer name. I need to display only CustomerCode in the ComboBox cell after user selects one item from the drop down list.
How can I do this? Or should I come up with my own control which will have a different AutoCompleteCustomSource and display member value. Even I'm confused with that approach too.
Update: As no one has come up with any solution to my problem. Now I'm starting a bounty for that, also if anyone can suggest me other way to implement the same functionality, it would be great.
I've even tried to come up with my own control and tried to work on simple combobox to display a different value than the selected dropdown list, even that didn't work. Is there any other way to implement this? Any tips and tricks are greatly appreciable.
#Anurag: Here is the code which I've used.
Created a datagridview in the design mode. Created one column of type 'DataGridViewComboBoxColumn' that and named it as CustomerColumn.
In the designer file it looks like below:
private System.Windows.Forms.DataGridViewComboBoxColumn CustomerColumn;
This is the entity class which I've used for datasource
public class Customer
{
public int Id { get; set; }
public string CustCode { get; set; }
public string CustName { get; set; }
public string NameWithCode { get; set; }// CustCode - CustName format
}
In the form load event I'm doing the following:
CustomerColumn.DataSource = GetCustomers();
CustomerColumn.DisplayMember = "NameWithCode";
CustomerColumn.ValueMember = "Id";
I'm answering my own question because I've implemented my own solution to this by using custom control.
This custom control is created by keeping a textbox above combo box in such a way that only drop down button of combobox is visible.
Now I've created a custom column in datagridview deriving the DataGridViewEditingControl from my usercontrol.
I've added a property in Usercontrol which will take drop down list source from the control which is hosting datagridview.
Now in the EditingControlShowing event I'm setting this property as below
private void dataGridView2_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
if(dataGridView2.CurrentCell.ColumnIndex.Equals(0) && e.Control is UserControl1)
{
var uscontrol = e.Control as UserControl1;
uscontrol.DropDownListSource = source;
}
}
This drop down list source is used in the usercontrol to set the autocompletesource to the textbox and datasource to the combobox as below:
Whenever I set the DropDownDataSource I'm firing an event in the usercontrol which will do the following. This is to ensure that every time EditingControlShowing event occurs for this column in DataGridView, this source is updated for textbox and combobox in usercontrol.
private void DropDownSourceChanged(object sender, EventArgs eventArgs)
{
textBox1.AutoCompleteCustomSource = DropDownListSource;
textBox1.AutoCompleteMode = AutoCompleteMode.SuggestAppend;
textBox1.AutoCompleteSource = AutoCompleteSource.CustomSource;
comboBox1.DataSource = DropDownListSource;
}
Now whenever user starts typing in the textbox autocomplete source will display dropdown list with 'NameWithCode' values and if user selects one of them then I'll set it to the Text propery overidden in my usercontrol which will be used for the cell value in the DataGridView. Now based on the Textbox text (which is NameWithCode) I can get the code part and set it to the text property.
If user uses combobox dropdown button to select the item then I'll get the combobox selected text and set it in the Textbox which is ultimately used by the cell for getting value.
This way I could achieve the solution I want.
#Homam, solution also works but when I change the ComboBox's DropDownStyle to allow the user to type the value in the combobox it behaves weirdly and not getting up to the mark solution for my requirement. Hence I used this solution.
I know that this is not perfect solution, but I looked for a better one and I didn't find, so I went to a workaround
I did the following:
when the user open the ComboBox, I change the DisplayMember to "NameWithCode"
when the user close it, I return it to "CustCode"
You can Access to the ComboBox control by DataGridView.EditingControlShowing event for the DataGridView.
The code:
private void dataGridView1_EditingControlShowing(object sender,
DataGridViewEditingControlShowingEventArgs e)
{
var comboBox = e.Control as ComboBox;
comboBox.DropDown += (s1, e1) => comboBox.DisplayMember = "NameWithCode";
comboBox.DropDownClosed += (s2, e2) =>
{
// save the last selected item to return it after
// reassign the Display Member
var selectedItem = comboBox.SelectedItem;
comboBox.DisplayMember = "CustCode";
comboBox.SelectedItem = selectedItem;
};
}
Note: You have to start the DisplayMember with "CustCode"
Good luck!
Each time at the offensive of event dataGridView1_EditingControlShowing there is addition of new handlers for events comboBox.DropDown and comboBox.DropDownClosed. It results in the increase of number of these handlers and their repeated calls. This code decides this problem.
private void dataGridView1_EditingControlShowing(object sender,
DataGridViewEditingControlShowingEventArgs e)
{
var comboBox = e.Control as ComboBox;
comboBox.DropDown += comboBox_DropDown;
comboBox.DropDownClosed += comboBox_DropDownClosed;
}
private void comboBox_DropDown(object sender, System.EventArgs e)
{
var comboBox = sender as ComboBox;
if(comboBox != null)
{
comboBox.DropDown -= comboBox_DropDown;
comboBox.DisplayMember = "NameWithCode";
}
}
private void comboBox_DropDownClosed(object sender, System.EventArgs e)
{
var comboBox = sender as ComboBox;
if(comboBox != null)
{
comboBox.DropDownClosed -= comboBox_DropDownClosed;
var selectedItem = comboBox.SelectedItem;
comboBox.DisplayMember = "CustCode";
comboBox.SelectedItem = selectedItem;
}
}