I have this ListBox that displays items I dragged from my DataGridView. Items in ListBox displays their MenuCode. What I want to happen is I want to show the MenuPrice of each item I have on ListBox on a TextBox. I tried to do this but the MenuCode displays on that TextBox. Please see the image below.
Is it possible to have the MenuPrice displayed on that TextBox? I have done this code but I dont think this is right.
private void menuDataGrid_CellMouseDown(object sender, DataGridViewCellMouseEventArgs e) //this code triggers when I dragged an item from datagridview to listbox.
{
menuDataGrid.DoDragDrop(menuDataGrid.CurrentRow.Cells[3].Value.ToString(), DragDropEffects.Copy);
}
private void menuListBox_SelectedValueChanged(object sender, EventArgs e) //this is the code when I select an item on the listview, then appears at the textbox
{
pricetxtbox.Text = menuListBox.SelectedItem.ToString();
}
private void ShowDataToGrid() //datagrid code
{
db_connection();
MySqlDataAdapter datagrid = new MySqlDataAdapter();
string selectAll = "SELECT * FROM Menu";
datagrid.SelectCommand = new MySqlCommand(selectAll, connect);
DataTable tbl = new DataTable();
datagrid.Fill(tbl);
BindingSource bs = new BindingSource();
bs.DataSource = tbl;
menuDataGrid.DataSource = bs;
menuDataGrid.Columns[6].Visible = false;
menuDataGrid.Columns[7].Visible = false;
}
I'm going to assume that the MenuPrice is also present on the GridView at a different cell, say Cells[4].
Then you can do something like this
private void menuListBox_SelectedValueChanged(object sender, EventArgs e) //this is the code when I select an item on the listview, then appears at the textbox
{
foreach (DataGridViewRow row in menuDataGrid.Rows)
{
if (row.Cells[3].Value.ToString().Equals(menuListBox.SelectedItem.ToString()))
{
pricetxtbox.Text = row.Cells[4].Value.ToString();
break;
}
}
}
You should pack your data into an object class with properties you want to display and hold. For example:
public class MenuItem()
{
public float MenuPrice { get; set; }
public string MenuCode { get; set; }
}
If you store data of type MenuItem in your ListView, you will be able to do:
private void menuListBox_SelectedValueChanged(object sender, EventArgs e) textbox
{
var item = menu.ListBoxItem.SelectedItem as MenuItem;
if(item == null) return;
pricetxtbox.Text = item.MenuPrice;
}
This would be one way to do it, if you want to enhance your code you should probably consider using databinding for you textboxes.
Related
In C# i can easily get data from a SQL DataBase and put it in a DataGrid with this code :
private void GetPcListBtn_Click(object sender, RoutedEventArgs e)
{
string service = (string)ServiceCB.SelectedValue;
comm = new SqlCommand("select T_COLLABORATEURS.CO_IDENT,T_PC.PC_ID,T_PC.PC_NOM,T_PC.PC_MODEL," +
"T_PC.PC_DATE_MES,T_PC.PC_COMM,T_PC.SERV_ID from T_COLLABORATEURS, T_PC" +
$" where T_COLLABORATEURS.CO_ID = T_PC.CO_ID and T_PC.SERV_ID = '{service}' ", conn);
SqlDataAdapter dap = new SqlDataAdapter(comm);
DataTable dt = new DataTable();
dap.Fill(dt);
PC_DT.ItemsSource = dt.DefaultView;
}
Then on Datagrid SelectionChanged Event i can click on a row to get fields datas and put it in a texbox with this code :
// DataGrid SelectionChanged => Fill TexBox
private void PC_DT_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (PC_DT.SelectedItem is DataRowView oData)
{
string pcNom = (string)oData["PC_NOM"];
string pcModel = (string)oData["PC_MODEL"];
RefPcTxtBox.Text = $"{pcNom} / {pcModel}";
}
}
Now in a other application i want to use Linq To SQL to do exactly the same.
Fill DataGrid :
// Fill DataGrid
private void GetPcListBtn_Click(object sender, RoutedEventArgs e)
{
string service = (string)ServiceCB.SelectedValue;
DataClasses1DataContext dc = new DataClasses1DataContext();
var pcCo = from co in dc.T_COLLABORATEURS
join pc in dc.T_PC on co.CO_ID equals pc.CO_ID
where pc.SERV_ID == service
select new
{
pc.PC_ID,
co.CO_IDENT,
pc.PC_NOM,
pc.PC_MODEL,
pc.PC_DATE_MES,
pc.PC_COMM,
pc.SERV_ID
};
PC_DT.ItemsSource = pcCo;
}
But now how can i fill my TextBox by clicking a DataGrid row ??
private void PC_DT_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
// How to Fill my Textbox ??
}
Please try this.
First way:
// Or whenever grid you want to use please set this type
var Grid = sender as DataGrid;
if(Grid != null)
{
textbox = Grid.FieldName
}
Second way:
var currentRow = GridName.SelectedRows;
if(currentRow != null)
{
textbox = currentRow .FieldName
}
I am Developing a winforms application. I have two datagrid views populated from two different bindingsources(control). I am using these to implement the master detail approach. My problem is that when the first datagridview is populated using the binding source I can't select the first row of it ,because the first element in the binding source is defaultly selected and can't be selected. Can any one provide me a solution for this
As you say the first row is selected by default. So after populating the DataSource to your first GridView you can set the second GridView based on first entry. Later you check the selectionChanged Event to populate the second GridView based on selectedRow of your first one.
Code could look sth. like this:
private void PopulateDataSource()
{
dataGridView1.DataSource = myBindingSource;
DataRowView selectedRow;
if (dataGridView1.SelectedRows.Count > 0)
selectedRow = dataGridView1.SelectedRows[0] as DataRowView;
if (selectedRow != null)
dataGridView2.DataSource = myBindingSource2; //Set the BindingSource based on selectedRow in first Grid
}
private void dataGridView1_SelectionChanged(object sender, EventArgs e)
{
DataRowView selectedRow;
if (dataGridView1.SelectedRows.Count > 0)
selectedRow = dataGridView1.SelectedRows[0] as DataRowView;
if (selectedRow != null)
dataGridView2.DataSource = myBindingSource2; //Set the BindingSource based on selectedRow in first Grid
}
If this doesn't work let me know but should do the job.
UDPATE
Here is a similar example using the events and methods of the bindingSource:
private void Initialize()
{
RegisterBindingSourceEvents();
dataGridView1.DataSource = bindingSource1;
dataGridView2.DataSource = bindingSource2;
bindingSource1.DataSource = myDataSource;
}
private void RegisterBindingSourceEvents()
{
bindingSource1.DataSourceChanged += BindingSource1_DataSourceChanged;
bindingSource1.CurrentChanged += BindingSource1_CurrentChanged;
}
private void BindingSource1_CurrentChanged(object sender, EventArgs e)
{
DataRowView row = bindingSource1.Current as DataRowView;
if (row != null)
bindingSource2.DataSource = myDataSource2BasedOnRow;
}
private void BindingSource1_DataSourceChanged(object sender, EventArgs e)
{
DataRowView row = bindingSource1.Current as DataRowView;
if (row != null)
bindingSource2.DataSource = myDataSource2BasedOnRow;
}
Further you maybe can use:
bindingSource.MoveNext();
bindingSource.MoveFirst();
To simulate focusing seconde row and directly first row. A bit ugly but i would guess this fires current_changed (untested). Better use first approach.
UDPATE-2
I'm sorry to tell you that this is not possible in a beautiful manner. The problem is that the Current Property of your bindingList is always set if your DataSource contains items. So if the user select the same row as the bindingSource Current Property contains your event won't get called. I found a solution which works in my example. You will need one gridEvent and maybe have to do some improvments but the idea should do the job. Sorry but without gridEvent i can't solve this:
Notice that iam using List as DataSource for my Testcase. You got DataTable and have to cast to DataRowView instead of Dummy for sure.
private bool _automatedRowChange;
private void Initialize()
{
List<Dummy> dummies = new List<Dummy> { new Dummy { Id = 1, Text = "Test1" }, new Dummy { Id = 2, Text = "Test2" } };
bindingSource1.DataSource = dummies;
dataGridView1.DataSource = bindingSource1;
//So the first row isn't focused but the bindingSource Current Property still holds the first entry
//That's why it won't fire currentChange even if you click the first row. Just looks better for the user i guess
dataGridView1.ClearSelection();
bindingSource1.CurrentChanged += BindingSource1_CurrentChanged;
dataGridView1.CellClick += DataGridView1_CellClick;
}
private void DataGridView1_CellClick(object sender, DataGridViewCellEventArgs e)
{
var clickedRow = dataGridView1.Rows[e.RowIndex].DataBoundItem as Dummy;
var currentRow = bindingSource1.Current as Dummy;
if (clickedRow != null &&
currentRow != null &&
clickedRow.Equals(currentRow))
{
_automatedRowChange = true;
bindingSource1.MoveNext();
_automatedRowChange = false; //MovePrevious is based on the click and should load the dataSource2
bindingSource1.MovePrevious();
}
}
private void BindingSource1_CurrentChanged(object sender, EventArgs e)
{
if (!_automatedRowChange) //Check if you jump to next item automatically so you don't load dataSource2 in this case
{
//Set the second DataSource based on selectedRow
}
}
I have a form that allows a user to add players to a roster, by entering the player name and selecting, from a combo box, the division to which the player belongs.
When time comes to add the player to my TreeView control, the node that should display the division selected displays this text instead: System.Data.DataRowView
I got the code to implement this through MSDN here: https://msdn.microsoft.com/en-us/library/system.windows.forms.combobox.selecteditem%28v=vs.110%29.aspx
Here's the code in the load function of the form, to fill the combo box:
private void frm_add_players_Load(object sender, EventArgs e)
{
Divisions divs = new Divisions();
Players players = new Players();
DataTable dtDivisions = divs.GetActiveDivisions(); //divisions combo box
DataTable dtPlayers = players.GetPlayersByTourID(this.tourID);
//set the forms datatable
this.dt_players = dtPlayers;
//fill the combo box
this.cmbo_divisions.DataSource = dtDivisions;
this.cmbo_divisions.DisplayMember = "title";
this.cmbo_divisions.ValueMember = "ID";
this.cmbo_divisions.SelectedIndex = -1;
this.cmbo_divisions.Text = "Select a Division";
//set treeview imagelist
this.tview_roster.ImageList = tview_imagelist;
this.tview_roster.ImageIndex = 1; //division icon
//fill treeview
foreach (DataRow dr in dtPlayers.Rows)
{
FillPlayerTreeview(dr);
}
//expand treeview
this.tview_roster.ExpandAll();
this.ActiveControl = this.txt_player_name;
}
Here I call the function to add the player to the TreeView:
private void btn_add_Click(object sender, EventArgs e)
{
object selItem = cmbo_divisions.SelectedItem;
AddPlayerToTreeView(txt_player_name.Text, selItem.ToString());
}
And here is the function that adds the player:
private void AddPlayerToTreeView(string playerName, string division)
{
TreeNode[] tns = this.tview_roster.Nodes.Find(division, false); //try to find the division, if exists
TreeNode tn = new TreeNode();
if (tns.Length > 0) //division exists - add player
{
tn = this.tview_roster.Nodes[tns[0].Index].Nodes.Add(playerName, playerName);
tn.ImageIndex = 0; //player icon
}
else //division doesn't exist - add division, then add player
{
tn = this.tview_roster.Nodes.Add(division, division);
tn.ImageIndex = 1; //division icon
AddPlayerToTreeView(playerName, division);
}
}
And the result is this:
I'm not sure why it won't work.. and I'm at a loss. Any help would be appreciated.
Well, well... maybe something like the following.
Access the combo's data source, which is a DataTable, and extract selected row and column value using selected index. Maybe add some error handling, too.
private void btn_add_Click(object sender, EventArgs e)
{
var data = cmbo_divisions.DataSource as DataTable;
var row = data.Rows[cmbo_divisions.SelectedIndex];
var selected = row["title"].ToString();
AddPlayerToTreeView(txt_player_name.Text, selected);
}
Try this :
private void btn_add_Click(object sender, EventArgs e)
{
object selItem = cmbo_divisions.SelectedItem;
AddPlayerToTreeView(txt_player_name.Text, cmbo_divisions.SelectedItem as string);
}
ToString() will get the type name, but in that case the SelectedItem is a string.
Try with:
private void btn_add_Click(object sender, EventArgs e)
{
AddPlayerToTreeView(txt_player_name.Text, cmbo_divisions.Items[cmbo_divisions.SelectedIndex].Text);
}
EDIT: Updated to a better way
I found a way to add a combobox to DataGridview (Winform) cell, but I have not found an event like ItemDataBound of DataGridView to set a value to comboBox. And do not know how to set a selected value of a comboBox to DataItem property of a current row (of a DataGridView) :(
Please give me some clues to do this task
Thanks you so much
You can use below method to add data to a combobox in gridview. If you dont have a list you can add items to the combobox as:
cmbdgv.Items.Add("Test");
private void bindDataToDataGridViewCombo() {
DataGridViewComboBoxColumn cmbdgv = new DataGridViewComboBoxColumn();
List<String> itemCodeList = new List<String>();
cmbdgv.DataSource = itemCodeList;
cmbdgv.HeaderText = "Test";
cmbdgv.Name = "Test";
cmbdgv.Width = 270;
cmbdgv.Columns.Add(dgvCmbForums);
cmbdgv.Columns["Test"].DisplayIndex = 0;
}
After adding if you want to capture the combobox selection change you can use below event in the datagridview.
ComboBox cbm;
DataGridViewCell currentCell;
private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
if (e.Control is ComboBox)
{
cbm = (ComboBox)e.Control;
if (cbm != null)
{
cbm.SelectedIndexChanged += new EventHandler(cbm_SelectedIndexChanged);
}
currentCell = this.dataGridView1.CurrentCell;
}
}
void cbm_SelectedIndexChanged(object sender, EventArgs e)
{
this.BeginInvoke(new MethodInvoker(EndEdit));
}
void EndEdit()
{
if (cbm != null)
{
string SelectedItem=cbm.SelectedItem.ToString();
int i = dataGridView1.CurrentRow.Index;
dataGridView1.Rows[i].Cells["Test"].Value = SelectedItem;
}
}
If you are trying to set the value to a Combobox in a DataGridView, see if this answer will help.
To get the selected item of the Combobox (example):
comboBox.SelectedIndexChanged += new EventHandler(comboBox_ComboSelectionChanged);
private void comboBox_ComboSelectionChanged(object sender, EventArgs e)
{
if (myDGV.CurrentCell.ColumnIndex == 5)
{
int selectedIndex;
string selectedItem;
selectedIndex = ((ComboBox)sender).SelectedIndex; // handle an error here.
// get the selected item from the combobox
var combo = sender as ComboBox;
if (selectedIndex == -1)
{
MessageBox.Show("No value has been selected");
}
else
{
// note that SelectedItem may be null
selectedItem = combo.SelectedItem.ToString();
if (selectedItem != null)
{
// Your code
private void deleteDisplayGamesButton_Click(object sender, EventArgs e)
{
//Game game = new Game(homeTeamComboBox.Text, int.Parse(homeScoreUpDown.Value.ToString()), awayTeamComboBox.Text, int.Parse(awayScoreUpDown.Value.ToString()));
deleteDisplayGamesListView.Items.Clear();
deleteDisplayGamesListView.View = View.Details;
foreach (Game currentgame in footballLeagueDatabase.games)
{
ListViewItem row = new ListViewItem();
row.SubItems.Add(currentgame.HomeTeam.ToString());
row.SubItems.Add(currentgame.HomeScore.ToString());
row.SubItems.Add(currentgame.AwayTeam.ToString());
row.SubItems.Add(currentgame.AwayScore.ToString());
deleteDisplayGamesListView.Items.Add(row);
}
}
I need to pass the values from above ListView control to following text boxes when I use the deleteDisplayGamesListView_SelectedIndexChanged method.
private void deleteDisplayGamesListView_SelectedIndexChanged(object sender, EventArgs e)
{
deleteModifyHomeTeamTxt.Text = "";
deleteModifyHomeScoreUpDown.Text = "";
deleteModifyAwayTeamTxt.Text = "";
deleteModifyAwayScoreUpDown.Text = "";
foreach (Game currentgame in footballLeagueDatabase.games);
{
?-----------------------------
}
}
Futhermore I need to clear the row after inserting to the textboxes,which i selected from the ListView Control.
If you know how to do this please let me know.
You should have access to your deleteDisplayGamesListView from within the SelectedIndexChanged event handler.
This should let you access the ListViewItems and their SubItems.