I want to store Objects of the class Rezept in the list List RezepteListe. After that I want to filter that RezepteListe regarding their NameID. But obviously I dont get the Filter() Method run on my RezepteListe.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public List<Rezept> RezepteListe = new List<Rezept>();
private void button1_Click(object sender, EventArgs e)
{
Rezept Kartoffelsalat = new Rezept("Kartoffelsalat");
textBox1.Text = Kartoffelsalat.NameID;
RezepteListe.Add(Kartoffelsalat);
textBox1.Text = RezepteListe.Where(x => x.NameID == "Kartoffelsalat");
List<String> liste2 = new List<string>();
liste2.Add("Hallo");
textBox1.Text= liste2.Find(x => x == "Hallo");
}
}
public class Rezept
{
public List<string> Zutat { get; set; }
public string NameID { get; set; }
public Rezept(string NameID)
{
this.NameID = NameID;
}
}
Related
The ListBox's DataSource is bound to Detail.Tags.
When I select the first row, ListBox populates as expected.
When I select the second row, the expected (and desired) result is that the ListBox simply displays nothing, because ItemB's Detail property is purposely null for demonstration purposes, so ItemB's Detail.Tags doesn't exist.
Actual result is that program crashes to desktop with System.ArgumentException: 'Complex DataBinding accepts as a data source either an IList or an IListSource.'
Minimal reproducible example:
public partial class Form1 : Form
{
private readonly IList<Item> _items;
private BindingSource _bs = new BindingSource(){ DataSource = typeof(Item) };
public Form1()
{
InitializeComponent();
_items = GenerateSampleItems();
}
private void Form1_Load(object sender, EventArgs e)
{
dataGridView1.DataSource = _items;
listBox1.DataBindings.Add(new Binding("DataSource", _bs, "Detail.Tags", false, DataSourceUpdateMode.Never));
}
private void DataGridView1_SelectionChanged(object sender, EventArgs e)
{
if (dataGridView1.SelectedRows.Count == 1)
{
_bs.DataSource = dataGridView1.SelectedRows[0].DataBoundItem;
}
else
{
_bs.DataSource = typeof(Item);
}
}
private IList<Item> GenerateSampleItems()
{
return new List<Item>()
{
new Item()
{
Name = "ItemA"
,Detail = new Detail()
{
Expiration = new DateTime(2024,1,1)
,Tags = new BindingList<Tag>(new List<Tag>()
{
new Tag()
{
TagName = "FirstT"
,TagValue = "FirstV"
}
,new Tag()
{
TagName = "SecondT"
,TagValue = "SecondV"
}
})
}
}
,new Item()
{
Name = "ItemB"
// Detail purposely omitted
}
,new Item()
{
Name = "ItemC"
// Detail purposely omitted
}
};
}
}
class Item
{
public string Name { get; set; }
public Detail Detail { get; set; }
}
public class Detail
{
public DateTime Expiration { get; set; }
public BindingList<Tag> Tags { get; set; }
}
public class Tag
{
public string TagName { get; set; }
public string TagValue { get; set; }
}
You can solve this problem by Creating a BindingSource for each model:
Main BindingSource where its DataSource property is set to a list of Item. This one is the DataGridView.DataSource.
Second BindingSource to navigate the Detail data members of the main BindingSource.
Third one to navigate and display the Tags data members of the detail's BindingSource. This one is the ListBox.DataSource.
public partial class Form1 : Form
{
private IList<Item> _items;
private BindingSource _bsItems, _bsDetail, _bsTags;
public Form1()
{
InitializeComponent();
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
_items = GenerateSampleItems();
_bsItems = new BindingSource(_items, null);
_bsDetail = new BindingSource(_bsItems, "Detail");
_bsTags = new BindingSource(_bsDetail, "Tags");
dataGridView1.DataSource = _bsItems;
listBox1.DataSource = _bsTags;
}
protected override void OnFormClosed(FormClosedEventArgs e)
{
base.OnFormClosed(e);
_bsItems.Dispose();
_bsDetail.Dispose();
_bsTags.Dispose();
}
private IList<Item> GenerateSampleItems()
{
return new List<Item>()
{
new Item()
{
Name = "ItemA",
Detail = new Detail
{
Expiration = new DateTime(2024,1,1),
Tags = new BindingList<Tag>(new List<Tag>()
{
new Tag
{
TagName = "FirstT",
TagValue = "FirstV"
},
new Tag
{
TagName = "SecondT",
TagValue = "SecondV"
}
})
}
},
new Item()
{
Name = "ItemB"
// Detail purposely omitted
},
new Item()
{
Name = "ItemC"
// Detail purposely omitted
}
};
}
}
// Elsewhere within the project's namespace
public class Item
{
public string Name { get; set; }
public Detail Detail { get; set; }
// Optional: Change, remove as needed...
public override string ToString()
{
return $"Name: {Name} - Detail: {Detail}";
}
}
public class Detail
{
public DateTime Expiration { get; set; }
public BindingList<Tag> Tags { get; set; }
// Optional: Change, remove as needed...
public override string ToString()
{
var tags = $"[{string.Join(", ", Tags)}]";
return $"Expiration: {Expiration} - Tags: {tags}";
}
}
public class Tag
{
public string TagName { get; set; }
public string TagValue { get; set; }
// Optional: Change, remove as needed...
public override string ToString()
{
return $"{TagName}: {TagValue}";
}
}
That's all. No need to add DataBindings nor to handle the grid's SelectionChanged event as shown in your code snippet.
On the other hand, if you need to display the selected Item.Detail.Tags, then you need to flatten them in a list whenever the grid's selection changes and bind the result to the ListBox.
// +
using System.Linq;
public partial class Form1 : Form
{
private BindingSource _bsItems;
public Form1() => InitializeComponent();
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
_bsItems = new BindingSource(GenerateSampleItems(), null);
dataGridView1.DataSource = _bsItems;
}
protected override void OnFormClosed(FormClosedEventArgs e)
{
base.OnFormClosed(e);
_bsItems.Dispose();
}
private void dataGridView1_SelectionChanged(object sender, EventArgs e)
{
listBox1.DataSource = dataGridView1.SelectedCells
.Cast<DataGridViewCell>()
.Select(cell => cell.OwningRow).Distinct()
.Where(row => (row.DataBoundItem as Item)?.Detail != null)
.SelectMany(row => (row.DataBoundItem as Item).Detail.Tags)
.ToList();
}
}
I've been tasked with a project where I have to use c# to create forms that digest a list of objects from a file, and is then able to pass the list to another window.
public class Food
{
public string Name;
public string Category;
public int Price;
}
public class Ingredient
{
public string Name;
public string Category;
public decimal PricePerUnit;
public decimal Quantity;
public Ingredient(string pName, string pCategory, decimal pPricePerUnit, decimal pQuantity)
{
Name = pName;
Category = pCategory;
PricePerUnit = pPricePerUnit;
Quantity = pQuantity;
}
}
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
List<Ingredient> Inventory = CallInventoryFile();
}
private void inventoryButton_Click(object sender, RoutedEventArgs e)
{
InventoryWindow wnd = new InventoryWindow();
wnd.ShowDialog();
}
public List<Ingredient> CallInventoryFile()
{
List<Ingredient> ProcessedInventory = new List<Ingredient>();
try
{
string[] fileLines = File.ReadAllLines("Inventory.txt");
//Reading in the file
for (int i = 0; i < fileLines.Length; i++)
{
string[] CurrentLine = fileLines[i].Split(',');
string Name = CurrentLine[0].Trim();
string Category = CurrentLine[1].Trim();
decimal PricePerUnit = decimal.Parse(CurrentLine[2].Trim());
decimal Quantity = decimal.Parse(CurrentLine[3].Trim());
Ingredient IngredientToAdd = new Ingredient(Name, Category, PricePerUnit, Quantity);
ProcessedInventory.Add(IngredientToAdd);
}
return ProcessedInventory;
}
catch
{
//if we get here read in failed
MessageBox.Show("There was an error reading in the file");
return ProcessedInventory;
}
}
Which I then have to move onto this window
public InventoryWindow()
{
InitializeComponent();
categoryComboBox.Items.Add("All");
categoryComboBox.Items.Add("Pizza");
categoryComboBox.Items.Add("Burger");
categoryComboBox.Items.Add("Sundry");
categoryComboBox.SelectedValue = "All";
}
private void listBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
}
private void categoryComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
}
}
}
My question is how can i pass the results of Inventory from MainWindow to InventoryWindow.
You can just pass inside the constructor ,
InventoryWindow wnd = new InventoryWindow(Inventory);
wnd.ShowDialog();
Then,
public InventoryWindow(List<Ingredient> inputList)
{
}
I'm working on a custom UI for Tracking stocks, although one UI I've made has caused an issue that I can't locate. I keep getting the error: "Inconsistent accessibility: parameter type 'SCM_Addin.Funds.TrackFund[]' is less accessible than method 'SCM_Addin.Forms.frm_FundTracker.frm_FundTracker(SM_Addin.Funds.TrackFund[])'
I've checked the protection in my classes, but I can't find any private variables that would hinder the accessibility in my code. Here is the code:
frm_FundTracker:
namespace SCM_Addin.Forms
{
public partial class frm_FundTracker : Form
{
public frm_FundTracker()
{
InitializeComponent();
}
public frm_FundTracker(String[] fundsToAdd, Double[] ePrices, Double[] cPrices)
{
InitializeComponent();
int index = 0;
foreach (String fund in fundsToAdd)
{
ListViewItem newFundItem = new ListViewItem(fund);
newFundItem.SubItems.Add(ePrices[index].ToString());
newFundItem.SubItems.Add(cPrices[index].ToString());
this.list_Tracker.Items.Add(newFundItem);
index++;
}//END LOADING COLUMNS
}//END FRM_FUNDTRACKER WITH ARRAYS
public frm_FundTracker(TrackFund[] funds)
{
InitializeComponent();
foreach (TrackFund fund in funds)
{
ListViewItem newFundItem = new ListViewItem(fund.symbol);
newFundItem.SubItems.Add(fund.entryPrice.ToString());
newFundItem.SubItems.Add(fund.currentPrice.ToString());
this.list_Tracker.Items.Add(newFundItem);
}
}//END FRM_FUNDTRACKER WITH FUNDS
private void btn_Done_Click(object sender, EventArgs e)
{
if (MessageBox.Show("Close Form?", "Close Form?", MessageBoxButtons.YesNo) == System.Windows.Forms.DialogResult.Yes)
{
this.Dispose();
}
}
}
}
Fund Class:
namespace SCM_Addin
{
class Fund
{
public String symbol { get; set; } //Symbol of the fund to be used
private int fundRow { get; set; } //Fund's spot in the Stats Sheet.
private String url1, url2, url3;
private HtmlAgilityPack.HtmlDocument doc;
private DataPuller puller;
private Dictionary<String, String> fundStats;
private SqlConnection conn;
public Fund(String sym)
{
this.symbol = sym;
this.doc = new HtmlAgilityPack.HtmlDocument();
this.puller = new DataPuller();
this.url1 = "http://finance.yahoo.com/q?s=" + this.symbol;
this.url2 = "http://finance.yahoo.com/q/ks?s=" + this.symbol;
this.url3 = "http://www.profitspi.com/stock-quote/" + this.symbol + ".aspx";
this.fundStats = new Dictionary<string, string>();
this.conn = null;
}
TrackFund class (Extends Fund)
namespace SCM_Addin.Funds
{
class TrackFund : Fund
{
public double entryPrice { get; set; }
public double currentPrice { get; set; }
public TrackFund(String sym, double entryP, double curP) : base(sym)
{
this.entryPrice = entryP;
this.currentPrice = curP;
}
}
}
This is my first time really extending a class in C#, so if I'm extending wrong, I guess that could be it.
Default accessibility for a class will be internal, so:
class Fund
//and
class TrackFund : Fund
...should be
public class Fund
//and
public class TrackFund : Fund
Make the TrackFund class public.
public class TrackFund : Fund
{
....
}
I have a property Grid as follows:
I want to copy the complete content of the property grid to a data grid view(dataGeriView1) when submit button is clicked.
How to do this?
Please help.
private void Submit_Click(object sender, EventArgs e)
{
//propertyGrid1.SelectedObject = this;
dataGridView1.Columns.Add("Property", "Property");
dataGridView1.Columns.Add("Value", "Value");
GridItem gi = propertyGrid1.SelectedGridItem;
while (gi.Parent != null)
gi = gi.Parent;
foreach (GridItem item in gi.GridItems)
ParseGridItems(item); //recursive
dataGridView1.Sort(dataGridView1.Columns["Property"], ListSortDirection.Ascending);
}
private void ParseGridItems(GridItem gi)
{
if (gi.GridItemType == GridItemType.Category)
foreach (GridItem item in gi.GridItems)
ParseGridItems(item);
dataGridView1.Rows.Add(gi.Label, gi.Value);
}
Adapted from https://stackoverflow.com/a/12109186/1163434
Below is a sample snippet i have created to solve the above issue. Create a DataGridview by adding Columns Name,Age,Email,Phone.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
Student std = new Student {Name = "Vimal" , Phone = "PhoneValue", Email="mymail",Age=24};
propertyGrid1.SelectedObject= std;
}
private void button1_Click(object sender, EventArgs e)
{
int index = dataGridView1.Rows.Count - 1;
Student std = (Student)propertyGrid1.SelectedObject;
dataGridView1.Rows[index].Cells["Name"].Value = std.Name;
dataGridView1.Rows[index].Cells["Age"].Value = std.Age;
dataGridView1.Rows[index].Cells["Email"].Value = std.Email;
dataGridView1.Rows[index].Cells["Phone"].Value = std.Phone;
}
}
public class Student
{
public int Age { get; set; }
public string Email { get; set; }
public string Name { get; set; }
public string Phone { get; set; }
}
I have to use a ListBox for this.
I currently know how to remove from a ListBox using this code:
private void removeButton_Click(object sender, EventArgs e)
{
REMOVE();
}
private void REMOVE()
{
int c = lstCart.Items.Count - 1;
for (int i = c; i >= 0; i--)
{
if (lstCart.GetSelected(i))
{
lstCart.Items.RemoveAt(i);
}
}
}
But what I have found is that when I add another item, it clears the ListBox and shows each item from the list, so it includes the 'removed' item because it wasn't removed from the list, only the ListBox.
I'm thinking that what I need to do is remove the selected line from the List, then clear the ListBox and repopulate it with the updated List data. But I'm struggling to find out how to do this.
Form1:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void addButton_Click(object sender, EventArgs e)
{
OrderItem currentItem = new OrderItem(txtItemName.Text,
Decimal.Parse(txtPrice.Text), (int)numQTY.Value);
myBasket.Add(currentItem);
lstCart.Items.Clear();
foreach (OrderItem i in myBasket)
{
lstCart.Items.Add(String.Format("{0,-40}
{1,-40} {2,-40} {3,-40}", i.ProductName,
i.Quantity.ToString(), i.LatestPrice.ToString(),
i.TotalOrder.ToString()));
}
txtItemTotal.Text = "£" + myBasket.BasketTotal.ToString();
txtItemCount.Text = myBasket.Count.ToString();
}
private void removeButton_Click(object sender, EventArgs e)
{
int c = lstCart.Items.Count - 1;
for (int i = c; i >= 0; i--)
{
if (lstCart.GetSelected(i))
{
lstCart.Items.RemoveAt(i);
}
}
????
}
}
ShoppingBasket class:
public class ShoppingBasket
{
public ShoppingBasket()
{
}
public new void Add(OrderItem i)
{
base.Add(i);
calcBasketTotal();
}
private void calcBasketTotal()
{
BasketTotal = 0.0M;
foreach (OrderItem i in this)
{
BasketTotal += i.TotalOrder;
}
}
public new void Remove(OrderItem i)
{
????
}
}
OrderItem class:
public class OrderItem
{
public OrderItem(string productName,
decimal latestPrice, int quantity)
{
ProductName = productName;
LatestPrice = latestPrice;
Quantity = quantity;
TotalOrder = latestPrice * quantity;
}
public string ProductName { get; set; }
public decimal LatestPrice { get; set; }
public int Quantity { get; set; }
public decimal TotalOrder { get; set; }
}
Your add method calls Add() on a base class. Do you have a remove on your base class? If so, use that. Otherwise change your ShoppingBasket class to be:
The Orders list stores your OrderItems. Add and Remove from this list.
public class ShoppingBasket
{
public List<OrderItem> Orders { get; set; }
public ShoppingBasket()
{
Orders = new List<OrderItem>();
}
public void Add(OrderItem orderItem)
{
Orders.Add(orderItem);
}
public void Remove(OrderItem orderItem)
{
Orders.Remove(orderItem);
}
}
Usage:
var basket = new ShoppingBasket();
basket.Add( new OrderItem { OrderItemId = 1, ... } );
// Remove an OrderItem
basket.Remove( new OrderItem { OrderItemId = 1 } );