I am working on Webforms (no MVC) I have the following scenario. I want to get ID of selected text of dropdown and insert on click event. but it is showing conversion error from string to EFCode.Department.
Code
EmployeeDbContext db = new EmployeeDbContext();
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
DropDownList1.DataSource = db.Departments.ToList();
DropDownList1.DataBind();
}
GridView1.DataSource = db.Departments.Include("Employees").ToList();
GridView1.DataBind();
}
protected void Button1_Click(object sender, EventArgs e)
{
Employee emp = new Employee(){Name = TextBox1.Text,
Gender= TextBox2.Text,
Salary = float.Parse(TextBox3.Text),
**Department = DropDownList1.SelectedValue**}; // error here
db.Employees.Add()
db.SaveChanges();
}
public class Department
{
public int ID { get; set; }
public string Name { get; set; }
public string Location { get; set; }
public List<Employee> Employees { get; set; }
}
public class Employee
{
public int ID { get; set; }
public string Name { get; set; }
public string Gender { get; set; }
public float Salary { get; set; }
**public Department Department { get; set; }**
}
public class EmployeeDbContext : DbContext
{
public DbSet<Employee> Employees { get; set; }
public DbSet<Department> Departments { get; set; }
}
you cannot use string substitute department object
when you execute the code the relation will be int , there for you must use conversion to Int32
Employee emp = new Employee(){Name = TextBox1.Text,
Gender= TextBox2.Text,
Salary = float.Parse(TextBox3.Text),
Department = db.GetDepartmentByID(Convert.ToInt32(DropDownList1.SelectedValue))};
Employee emp = new Employee(){Name = TextBox1.Text,
Gender= TextBox2.Text,
Salary = float.Parse(TextBox3.Text),
Department = db.FirstOrDefault(x => x.Name == DropDownList1.SelectedValue)};
You cant declare department as a property.. I have modified your code in the way that Name will be retrived from your department table which is in your database by using the dropDownList1.SelectValue.. Not sure whether this is your requirement..
Code:
protected void Button1_Click(object sender, EventArgs e)
{
Employee emp = new Employee(){
Name = TextBox1.Text,
Gender= TextBox2.Text,
Salary = float.Parse(TextBox3.Text),
Department = new Department()
{
Name = db.Department.Where(s => s.Id == dropDownList1.SelectValue).Select(s.Name).FirstOrDefault();
},
};
db.Employees.Add();
db.SaveChanges();
}
Your problem is in the page load
if (!IsPostBack)
{
DropDownList1.DataSource = db.Departments.ToList();
DropDownList1.DataBind();
}
You need to add this
if (!IsPostBack)
{
DropDownList1.DataSource = db.Departments.ToList();
DropDownList1.DataTextField = "Name";
DropDownList1.DataValueField = "ID"; **//This will get the id**
DropDownList1.DataBind();
}
Also convert to Int: (Convert.ToInt32(Dropdownlist.SelectedValue))
Related
I added 3 columns.
The modified attribute values are as follows.
View - Details
Onwer - True
GirdLines - True
FullRowSelect - True
namespace TestWinForm
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void add_Click(object sender, EventArgs e)
{
//listView1.BeginUpdate();
string[] row = { "123", "456", "789" };
ListViewItem list_view = new ListViewItem(row);
listView1.Items.Add(list_view);
textBox1.Text = listView1.Items.Count.ToString();
//listView1.EndUpdate();
}
}
}
It is a code that updates the number of current rows to the textbox1 after adding a data row every time the add button is clicked.
Obviously, The number of rows keeps going up.... but the data is not output to listView1.
Which part should I check?
What you have should work in detail view with columns added. Here is an example
Design view
In this case a instance of the following class is used so later we can get information about a specific row.
public class Contact
{
public int CustomerIdentifier { get; set; }
public string CompanyName { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string PhoneTypeDescription { get; set; }
public string PhoneNumber { get; set; }
public string CountryName { get; set; }
public string[] ItemArray => new[]
{
CompanyName,
FirstName,
LastName,
PhoneNumber,
CountryName
};
}
Code to do a mock add
private void AddRowButton_Click(object sender, EventArgs e)
{
var companyName = "Just added";
Contact contact = new Contact()
{
CompanyName = companyName,
FirstName = "Karen",
LastName = "Payne",
PhoneNumber = "123-333-4444",
CountryName = "USA"
};
ownerContactListView.Items.Add(
new ListViewItem(contact.ItemArray)
{
Tag = contact.CustomerIdentifier
});
CountLabel.Text = $#"Row count: {ownerContactListView.Items.Count}";
var index = ownerContactListView.Items.IndexOf(
ownerContactListView.FindItemWithText(companyName));
ownerContactListView.Items[index].Selected = true;
ownerContactListView.EnsureVisible(index);
ActiveControl = ownerContactListView;
}
After adding the row above (note I shorten the form so what you see is a partial view)
You can see the entire the initial load, see the following.
Havent used Winforms in ages, but I remember that using a binding source was more reliable
var bindingSource = new BindingSource();
bindingSource.DataSource = dataTable;
grid.DataSource = bindingSource;
//Add data to dataTable and then call
bindingSource.ResetBindings(false)
As I understand it, ComboBox columns are more dynamic for binding in DataGridView than standard columns, and this flexibility can be used to use DisplayMembers from second-order properties. This approach is the first mentioned here by Mr. Aghaei.
However, I'm not getting it right. My application still throws the exception that "Name" doesn't exist.
public void CreateEmployeeTable()
{
DataGridViewComboBoxColumn jobTitleColumn = new DataGridViewComboBoxColumn();
jobTitleColumn.HeaderText = "Job Title";
jobTitleColumn.DataPropertyName = "JobTitle";
jobTitleColumn.DisplayStyle = DataGridViewComboBoxDisplayStyle.Nothing;
jobTitleColumn.DataPropertyName = "ID";
jobTitleColumn.DataSource = globalEmployeeList;
jobTitleColumn.ValueMember = "ID";
jobTitleColumn.DisplayMember = "Name";
jobTitleColumn.ReadOnly = true;
employeeGridView.AutoGenerateColumns = false;
employeeGridView.ColumnCount = 2;
employeeGridView.Columns[0].HeaderText = "Employee ID";
employeeGridView.Columns[0].DisplayIndex = 0;
employeeGridView.Columns[0].DataPropertyName = "ID";
employeeGridView.Columns[1].HeaderText = "Name";
employeeGridView.Columns[1].DataPropertyName = "ListView";
employeeGridView.Columns[1].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
employeeGridView.Columns.Add(jobTitleColumn);
employeeGridView.DataSource = globalEmployeeList;
}
Here is the class definition:
public class EmployeeModel
{
public int ID { get; set; }
public string LastName { get; set; }
public string FirstName { get; set; }
public string Nickname { get; set; }
public DepartmentModel Department { get; set; }
public TitleModel JobTitle { get; set; }
public DateTime HireDate { get; set; }
public List<EmailModel> EmailList { get; set; } = new List<EmailModel>();
public List<PhoneModel> PhoneList { get; set; } = new List<PhoneModel>();
public List<RestrictionModel> RestrictionsList { get; set; } = new List<RestrictionModel>();
public List<CitationModel> CitationsList { get; set; } = new List<CitationModel>();
public List<CertificationModel> CertificationList { get; set; } = new List<CertificationModel>();
public string ListView
{
get
{
return $"{LastName}, {FirstName}";
}
}
public string ToEmailString()
{
IEnumerable<string> employeeEmailStrings = EmailList.Select(emmod => emmod.ToString());
string employeeEmailString = string.Join($"{Environment.NewLine}", employeeEmailStrings);
IEnumerable<string> certificationStrings = CertificationList.Select(clistmod => clistmod.ToString());
string certificationString = string.Join($"{Environment.NewLine}", certificationStrings);
IEnumerable<string> phoneStrings = PhoneList.Select(plistmod => plistmod.ToString());
string phoneString = string.Join($"{Environment.NewLine}", phoneStrings);
return $"{FirstName}, {LastName}: {Environment.NewLine} -{JobTitle.Name}- {Environment.NewLine} {employeeEmailString} {Environment.NewLine} {certificationString} {Environment.NewLine} {phoneString}";
}
public class EmailModel
{
public int ID { get; set; }
public string Address { get; set; }
public string Type { get; set; }
public override string ToString()
{
return $"{Address} ({Type})";
}
}
public class PhoneModel
{
public int ID { get; set; }
public string Number { get; set; }
public string Type { get; set; }
public override string ToString()
{
return $"{Number} ({Type})";
}
}
}
And the definition for TitleModel:
public class TitleModel
{
public string Name { get; set; }
public int ID { get; set; }
}
}
To support the post Show Properties of a Navigation Property in DataGridView (Second Level Properties) I've already shared a few example in the same post or this one which allows showing second level properties and allow editing them.
Here I will share a few more examples, each example has been written as a minimal complete verifiable example, you can just copy and paste in an empty form and they will work.
These are the examples:
Using ToString()
Using CellFormatting
Using ComboBox Column for Navigation Object
Using ComboBox Column for Foreign key column
Example - Using ToString()
When: You don't want to change JobTitle of Employee
How: By overriding ToString method of JobTitle
class JobTitle
{
public int Id { get; set; }
public string Name { get; set; }
public override string ToString()
{
return Name;
}
}
class Employee
{
public int Id { get; set; }
public string Name { get; set; }
public JobTitle JobTitle { get; set; }
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
var jobTitles = new List<JobTitle>() {
new JobTitle {Id= 1, Name="Manager" },
new JobTitle {Id= 2, Name="Employee" },
};
var employees = new List<Employee>() {
new Employee{ Id = 1, Name ="John", JobTitle = jobTitles[0] },
new Employee{ Id = 2, Name ="Jane", JobTitle = jobTitles[1] },
new Employee{ Id = 3, Name ="Jack", JobTitle = jobTitles[1] },
};
var dg = new DataGridView();
dg.Dock = DockStyle.Fill;
dg.DataSource = employees;
this.Controls.Add(dg);
}
Example - Using CellFormatting
When: You don't want to change JobTitle of Employee
How: By handling CellFormatting event of DataGridView and setting Value of the event args to a string representation of JobTitle
class JobTitle
{
public int Id { get; set; }
public string Name { get; set; }
}
class Employee
{
public int Id { get; set; }
public string Name { get; set; }
public JobTitle JobTitle { get; set; }
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
var jobTitles = new List<JobTitle>() {
new JobTitle {Id= 1, Name="Manager" },
new JobTitle {Id= 2, Name="Employee" },
};
var employees = new List<Employee>() {
new Employee{ Id = 1, Name ="John", JobTitle = jobTitles[0] },
new Employee{ Id = 2, Name ="Jane", JobTitle = jobTitles[1] },
new Employee{ Id = 3, Name ="Jack", JobTitle = jobTitles[1] },
};
var dg = new DataGridView();
dg.Dock = DockStyle.Fill;
dg.DataSource = employees;
dg.CellFormatting += (obj, args) =>
{
if (args.RowIndex >= 0 &&
dg.Columns[args.ColumnIndex].DataPropertyName == "JobTitle")
args.Value = ((Employee)dg.Rows[args.RowIndex].DataBoundItem).JobTitle.Name;
};
this.Controls.Add(dg);
}
Example - Using ComboBox Column for Foreign key column
When: You want to be able to change the JobTitle of Employee and you have the foreign key column in your model.
How: Using a DataGridViewComboBoxColumn for that property, having a data source containing all job titles, and setting DisplayMember and ValueMember to proper properties.
class JobTitle
{
public int Id { get; set; }
public string Name { get; set; }
}
class Employee
{
public int Id { get; set; }
public string Name { get; set; }
public int JobTitleId { get; set; }
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
var jobTitles = new List<JobTitle>() {
new JobTitle {Id= 1, Name="Manager" },
new JobTitle {Id= 2, Name="Employee" },
};
var employees = new List<Employee>() {
new Employee{ Id = 1, Name ="John", JobTitleId = 1 },
new Employee{ Id = 2, Name ="Jane", JobTitleId = 2 },
new Employee{ Id = 2, Name ="Jack", JobTitleId = 2 },
};
var dg = new DataGridView();
dg.Dock = DockStyle.Fill;
dg.DataSource = employees;
dg.Columns.Add(new DataGridViewTextBoxColumn()
{
DataPropertyName = "Id", HeaderText = "Id"
});
dg.Columns.Add(new DataGridViewTextBoxColumn()
{
DataPropertyName = "Name", HeaderText = "Name"
});
dg.Columns.Add(new DataGridViewComboBoxColumn()
{
DataPropertyName = "JobTitleId",
HeaderText = "JobTitleId",
DataSource = jobTitles,
ValueMember = "Id",
DisplayMember = "Name",
});
this.Controls.Add(dg);
}
Example - Using ComboBox Column for Navigation Object
When: You want to be able to change the JobTitle of Employee and you don't have the foreign key column in your model, instead you want to use the navigation object in your model.
How: Using a DataGridViewComboBoxColumn for that property, having a data source containing all job titles, without setting DisplayMember and ValueMember to proper properties. Then handling CellFormatting to set the display value of the cell and handling CellParsing to get value from ComboBox and put into the cell.
class JobTitle
{
public int Id { get; set; }
public string Name { get; set; }
public override string ToString()
{
return Name;
}
}
class Employee
{
public int Id { get; set; }
public string Name { get; set; }
public JobTitle JobTitle { get; set; }
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
var jobTitles = new List<JobTitle>() {
new JobTitle {Id= 1, Name="Manager" },
new JobTitle {Id= 1, Name="Employee" },
};
var employees = new List<Employee>() {
new Employee{ Id = 1, Name ="John", JobTitle = jobTitles[0] },
new Employee{ Id = 2, Name ="Jane", JobTitle = jobTitles[1] },
new Employee{ Id = 2, Name ="Jack", JobTitle = jobTitles[1] },
};
var dg = new DataGridView();
dg.Dock = DockStyle.Fill;
dg.DataSource = employees;
dg.Columns.Add(new DataGridViewTextBoxColumn()
{
DataPropertyName = "Id", HeaderText = "Id"
});
dg.Columns.Add(new DataGridViewTextBoxColumn()
{
DataPropertyName = "Name", HeaderText = "Name"
});
dg.Columns.Add(new DataGridViewComboBoxColumn()
{
DataPropertyName = "JobTitle",
HeaderText = "JobTitle",
DataSource = jobTitles,
});
dg.CellFormatting += (obj, args) =>
{
if (args.RowIndex >= 0 &&
dg.Columns[args.ColumnIndex].DataPropertyName == "JobTitle")
{
args.Value =
((Employee)dg.Rows[args.RowIndex].DataBoundItem).JobTitle.ToString();
}
};
dg.CellParsing += (obj, args) =>
{
if (args.RowIndex >= 0 &&
dg.Columns[args.ColumnIndex].DataPropertyName == "JobTitle")
{
args.Value = ((ComboBox)dg.EditingControl).SelectedItem;
args.ParsingApplied = true;
}
};
this.Controls.Add(dg);
}
I'm trying to do a related combobox. I already have 2 comboboxes, but now I want to add a third.
I have this code for the 2nd combo box.
I'm using windows forms.
The entire code: https://repl.it/#devilonline/MuddyPartialBytecode#main.cs
private string[] GetCastById(int id)
{
return nomes.Where(line => line.movies_id== id).Select(l => l.nomes).ToArray();
}
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
comboBox1.Items.Clear();
int id = nomes[comboBox1.SelectedIndex].id;
foreach (string name1 in GetCastById(id))
{
this.comboBox1.Items.Add(name1);
}
}
print
It is obvious that you are clearing the Items of the comboBox1 then try to get the id of the selected item, which should throw an exception because no item will be selected by then:
comboBox1.Items.Clear(); // here the items are cleared
int id = nomes[comboBox1.SelectedIndex].id; // nomes[comboBox1.SelectedIndex] = -1
Based on your database, the cast table is related to the movies so each movie has a corresponding list of cast, you should then get the id of the selected movie rather than the selected nome:
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
comboBox1.Items.Clear();
int id = movies[comboBoxMovie.SelectedIndex].id; // here we used comboBoxMovie
foreach (string name1 in GetCastById(id))
{
this.comboBox1.Items.Add(name1);
}
}
This is a great opportunity to use databinding through a System.ComponentModel.BindingList<>. Below is a working example. Note, I've added get methods inside the classes for simplicity of populating the ComboBoxes for this example.
using System;
using System.Collections.Generic;
using System.Linq;
using System.ComponentModel;
public class Form1
{
class Category
{
public int Id { get; set; }
public string Name { get; set; }
public Category(int id, string name)
{
this.Id = id;
this.Name = name;
}
public static List<Category> GetCategories()
{
return new List<Category>()
{
new Category(1, "Action"),
new Category(2, "Comedy")
};
}
}
class Movie
{
public int Id { get; set; }
public string Name { get; set; }
public int CategoryId { get; set; }
public Movie(int id, string name, int catId)
{
this.Id = id;
this.Name = name;
this.CategoryId = catId;
}
public static List<Movie> GetMovies()
{
return new List<Movie>()
{
new Movie(1, "Rambo", 1),
new Movie(2, "Delta Force", 1),
new Movie(3, "Elf", 2),
new Movie(4, "Space Balls", 2)
};
}
}
class Cast
{
public int Id { get; set; }
public string Names { get; set; }
public int MovieId { get; set; }
public Cast(int id, string names, int movieId)
{
this.Id = id;
this.Names = names;
this.MovieId = movieId;
}
public static List<Cast> GetCast()
{
return new List<Cast>()
{
new Cast(1, "Silvester Stalone", 1),
new Cast(2, "Chuck Norris", 2),
new Cast(3, "Will Farrell", 3),
new Cast(4, "John Candy", 4)
};
}
}
private BindingList<Category> _categoryBindingList = new BindingList<Category>();
private BindingList<Movie> _moviesBindingList = new BindingList<Movie>();
private BindingList<Cast> _castBindingList = new BindingList<Cast>();
private void Form1_Load(object sender, EventArgs e)
{
// Your database calls would replace these Get methods.
Category.GetCategories().ForEach(x => _categoryBindingList.Add(x));
Movie.GetMovies().ForEach(x => _moviesBindingList.Add(x));
Cast.GetCast().ForEach(x => _castBindingList.Add(x));
ComboBox1.DataSource = _categoryBindingList;
ComboBox1.DisplayMember = "Name";
ComboBox2.DataSource = _moviesBindingList.Where(x => x.CategoryId == (Category)ComboBox1.SelectedValue.Id).ToList();
ComboBox2.DisplayMember = "Name";
ComboBox3.DataSource = _castBindingList.Where(x => x.MovieId == (Movie)ComboBox2.SelectedValue.Id).ToList();
ComboBox3.DisplayMember = "Names";
}
private void ComboBox1_SelectedValueChanged(object sender, EventArgs e)
{
ComboBox2.DataSource = _moviesBindingList.Where(x => x.CategoryId == (Category)ComboBox1.SelectedValue.Id).ToList();
ComboBox2.DisplayMember = "Name";
ComboBox3.DataSource = _castBindingList.Where(x => x.MovieId == (Movie)ComboBox2.SelectedValue.Id).ToList();
ComboBox3.DisplayMember = "Names";
}
private void ComboBox2_SelectedValueChanged(object sender, EventArgs e)
{
ComboBox3.DataSource = _castBindingList.Where(x => x.MovieId == (Movie)ComboBox2.SelectedValue.Id).ToList();
ComboBox3.DisplayMember = "Names";
}
}
System.Linq.Enumerable+WhereSelectListIterator`2[ShopApp_Sem2_Project.Item,System.String]
public class Item
{
#region Properties
public int ItemID { get; set; }
public string ProductName { get; set; }
public string Manufacturer { get; set; }
public string Category { get; set; }
public double Price { get; set; }
public string Info { get; set; }
public string Image { get; set; }
#endregion Properties
#region Constructors
public Item(int itemID, string product, string manufacturer, string category, double price, string info, string image)
{
ItemID = itemID;
Manufacturer = manufacturer;
Category = category;
ProductName = product;
Price = price;
Info = info;
Image = image;
}
#endregion Constructors
}
So this is my class with some properties and constructors which I'm using to create a shop. I populate a listbox called lbxCategories, but when trying to get any information after selecting from the listbox and using a linq statement I get that error seen above.
public partial class shopHome : Page
{
string connectionString = #"Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=C:\Users\Owner\Desktop\College Work\OOD\ShopApp_Sem2_Project\items.mdf;Integrated Security=True;";
List<Item> allItems = new List<Item>();
public shopHome()
{
InitializeComponent();
}
private void LbxCategories_Loaded(object sender, RoutedEventArgs e)
{
using (SqlConnection sqlCon = new SqlConnection(connectionString))
{
string query = "SELECT * FROM items ORDER BY itemID";
sqlCon.Open();
SqlCommand sqlCmd = new SqlCommand(query, sqlCon);
SqlDataReader dr = sqlCmd.ExecuteReader();
if(dr.HasRows)
{
while(dr.Read())
{
Item newItem = new Item(Convert.ToInt32(dr[0]), dr[1].ToString(), dr[2].ToString(), dr[3].ToString(), Convert.ToDouble(dr[4]), dr[5].ToString(), dr[6].ToString());
allItems.Add(newItem);
}
if(allItems != null)
{
var results = allItems.Select(x => x.Category).Distinct();
lbxCategories.ItemsSource = results;
}
}
sqlCon.Close();
}
}
private void LbxCategories_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
string selectedItem = lbxCategories.SelectedItem as string;
var results = allItems.Select(x => x.ProductName).ToString();
test.Text = results; // this is just to test and see if I can get any input which isn't gibberish
}
So when I run the code everything goes smoothly until I click on an item in the listbox which gives me this
In the middle I just stuck a textblock to output the ProductName to
Any help is greatly appreciated as I have projects due in a few days and need to get this out of the way
I'll be honest, it was a bit difficult to work out what you were trying to do with your code, but I think I have. Take a look at this:
private void LbxCategories_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (e.AddedItems != null && e.AddedItems.Count > 0)
{
string selected = (string)e.AddedItems[0];
string productName = (from i in allItems where i.Category == selected select i.ProductName).FirstOrDefault();
}
}
This will give you the ProductName of the first Item which has the selected category. If you actually want all the products matching that category, then you can take off FirstOrDefault from the end and it will give you an IEnumerable<String> of all the matching product names.
While doing JSON example, I have reached a point where i have a gridview and it should be bind to datasource. The datasource is in Json object
The code
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
Employee employee = new Employee();
var list = employee.CreateEmployees();
var query = from emp in list.AsEnumerable()
select new
{
id = (int)emp.EmployeeId,
name = (string)emp.Name,
nic = (string)emp.Nic,
salary = (int)emp.Salary
};
JObject o = JObject.FromObject(new
{
Employees = query
});
Response.Write(o);
Session["JsonEmployee"] = o;
}
LoadGrid();
}
For loading Grid:
void LoadGrid() {
List<Employee> lst = new List<Employee>();
var objects = (JObject)Session["JsonEmployee"];
foreach (var v in objects)
{
lst = JsonConvert.DeserializeObject<List<Employee>>(v.Value.ToString());
}
GridView1.DataSource = lst;
GridView1.DataBind();
}
All works fine but the only problem is that the EmployeeId is 0 for every employee.
Employee class is as:
public class Employee
{
public int EmployeeId { get; set; }
public string Name { get; set; }
public string Nic { get; set; }
public int Salary { get; set; }
.....
}
Note in the json object every employee has correct id but when it convert it to list getting employeeid 0 for every employee.
In the one object it's called id and in the other EmployeeId. Name them the same, it should solve the issue