I have a combobox for an item list that I populate using the following code:
List<string> comboboxItems = new List<string>();
foreach (var p in products)
{
var x = p.Product;
foreach (var pn in x)
{
comboboxItems.Add(pn.name + " :Qty " + pn.quantity_available
+ " :Tax " + pn.default_tax_tier);
}
}
cmbItems.DataSource = comboboxItems;
What should I do in order to get the value, pn.name only when the combobox item is selected?
Using WinForms.
You have to handle the event DataGridView.EditingControlShowing event, in there you can access the actual combobox and register the SelectedIndexChanged event handler like this:
//EditingControlShowing event handler for your dataGridView1
private void dataGridView1_EditingControlShowing(object sender,
DataGridViewEditingControlShowingEventArgs e){
if(dataGridView1.CurrentCell.OwningColumn == cmbItems){
var combo = e.Control as ComboBox;
combo.SelectedIndexChanged -= cmbItems_SelectedIndexChanged;
combo.SelectedIndexChanged += cmbItems_SelectedIndexChanged;
}
}
private void cmbItems_SelectedIndexChanged(object sender, EventArgs e){
var combo = sender as ComboBox;
//Note that SelectedItem may be null
var s = Convert.ToString(combo.SelectedItem);
int i = s.IndexOf(" :Qty");
var selectedName = i == -1 ? "" : s.Substring(0,i+1).TrimEnd();
//other code ...
}
you should create an item such as
public class CboItem
{
public string Text { get; set; }
public object Value { get; set; }
public override string ToString()
{
return Text;
}
}
then you can create easily using something like
CboItem item = new CboItem();
item.Text = "My Item";
item.Value = "Anything";
in the Value you can store your var pn whatever it is.
then you can retrieve like so :
((CboItem)comboBox1.SelectedItem).Value;
You will need to cast the result above to the proper type you stored inside as the Value is of type object.
We can also regular expressions to extract data from string.
Create string variable in the below format
string inputPattern = "{0} :Qty {1} :Tax {2}";
While inserting the data into combo box,
comboboxItems.Add(string.Format(inputPattern, p.Name, p.Quantity_Available, p.Tax));
After you added it, to extract the strings we can use Regex, code snippet below.
string extractPattern = "(?<Name>.*) :Qty (?<Qty>.*) :Tax (?<Tax>.*)";
foreach (var item in (comboBox1.DataSource as List<string>))
{
var matches = Regex.Match(item, extractPattern);
if (matches.Groups["Name"].Success)
{
MessageBox.Show(matches.Groups["Name"].Value);
}
if (matches.Groups["Qty"].Success)
{
MessageBox.Show(matches.Groups["Qty"].Value);
}
if (matches.Groups["Tax"].Success)
{
MessageBox.Show(matches.Groups["Tax"].Value);
}
}
Related
I've been looking online for a simple solution but can't seem to find any.
I simply want to generate a total price from all the item prices in my listview collection but can't seem to figure out how to do this.
How do I add all the product prices in my list and output them onto the total label?
Here's my code:
public ViewFBShoppingCart()
{
InitializeComponent();
ObservableCollection<FBProduct> fbproducts = new ObservableCollection<FBProduct>();
shoppingcartlistview.ItemsSource = fbproducts;
var producttitle = "Apple";
var productprice = "$37.95";
var productimage = "image link goes here";
var producttitle2 = "Pear";
var productprice2 = "$32.95";
var productimage2 = "image link goes here";
fbproducts.Add(new FBProduct
{
ProductName = producttitle,
ProductPrice = productprice,
ProductImage = productimage
});
fbproducts.Add(new FBProduct
{
ProductName = producttitle2,
ProductPrice = productprice2,
ProductImage = productimage2
});
}
I suggest not using formatted string like "$35.00" you can format it later using Text="{Binding ProductPrice, StringFormat='${0}'} in your .xaml file
But in that case: You can use Linq
string total = fbproducts.Select(a => new { Converted = Convert.ToDouble(a.ProductPrice.Replace("$", "")) }).ToList().Sum(a => a.Converted).ToString("#,0.00");
string TotalProductPrices(ObservableCollection<FBProduct> fbproducts)
{
var total = fbproducts.Sum(x => decimal.Parse(x.ProductPrice, NumberStyles.Currency));
return total.ToString("c");
}
Assuming you are following MVVM pattern, first subscribe to your collection's event fbproducts.CollectionChanged += fbproducts_CollectionChanged and then inside that method based on NotifyCollectionChangedEventArgs each time an item is added or removed you should raise the property changed event of a new readonly property that computes the sum using a loop or a 1-line Linq.
private void fbproducts_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if(e.Action == NotifyCollectionChangedAction.Add || e.Action == NotifyCollectionChangedAction.Remove)
{
RaisePropertyChanged(nameof(PriceSum));
}
}
public decimal PriceSum => fbproducts.Sum(x => decimal.Parse(x.ProductPrice.Substring(1)));
You should also consider changing ProductPrice type to decimal instead of string.
I'm new to C# so I will try to explain this to the best of my abillity.
I'm creating a simple podcast-application in C# and trying to use an XML-reader to recieve an RSS feed and then putting that information into diffrent winforms.
I've worked out how to get the main information I want into a listBox.
What I cannot figure out however, is to get another piece of information (the summary) from the RSS feed into a richTextBox by clicking a list item in the listBox.
The class I made to read the RSS feed.
List item
public class RSSreader
{
public static List<Tuple<string, string>> rssRead(string url)
{
string subject = "";
string summary = "";
var x = "";
var y = "";
var count = 0;
var list = new List<Tuple<string, string>>();
try
{
XmlReader reader = XmlReader.Create(url);
SyndicationFeed feed = SyndicationFeed.Load(reader);
reader.Close();
foreach (SyndicationItem item in feed.Items)
{
count++;
subject = item.Title.Text;
summary = item.Summary.Text;
x += count + " " + subject + " ";
list.Add(new Tuple<string, string>("Avsnitt " + count+ " " + subject, summary));
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
//Datahandler.SavePodFeed(list);
return list ;
}
}
public class RSSreader
{
public static List<Tuple<string, string>> rssRead(string url)
{
string subject = "";
string summary = "";
var x = "";
var y = "";
var count = 0;
var list = new List<Tuple<string, string>>();
try
{
//string urlX = "http://feeds.soundcloud.com/users/soundcloud:users:298230954/sounds.rss";
XmlReader reader = XmlReader.Create(url);
SyndicationFeed feed = SyndicationFeed.Load(reader);
reader.Close();
foreach (SyndicationItem item in feed.Items)
{
count++;
subject = item.Title.Text;
summary = item.Summary.Text;
x += count + " " + subject + " ";
list.Add(new Tuple<string, string>("Avsnitt " + count+ " " + subject, summary));
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
return list ;
}
}
What im using to populate the listbox
private void button1_Click(object sender, EventArgs e)
{
var list = RSSreader.rssRead(tbxURL.Text);
foreach (Tuple<string, string> item in list)
{
listBox2.Items.Add(item.Item1);
}
listBox2.Items.Add(RSSreader.rssRead(tbxURL.Text));
}
My take on populating the richTextBox from the listBox with the summary onclick.
private void listBox2_MouseClick(object sender, MouseEventArgs e)
{
var list = RSSreader.rssRead(tbxURL.Text);
foreach (Tuple<string, string> item in list)
{
if (item != listBox2.SelectedItem)
{
richTextBox1.Text = item.Item2.ToString();
}
}
}
I don't get any errors but it's only populating the richTextBox with the same information no matter which element in the list I click.
Here are a few pointers:
Make a class where you store the information from RSS for each element (eg. MyPodcastEntry.cs with properties Index (count), Subject, Summary, ...)
Populate those classes in your rssRead and add them to a List
Add that list to the listbox instead of using Tuple<>
Override ToString in that class to adjust how they are displayed in the listbox
This will help you keep and use the information from RSS. There is no need to run rssRead every time you click the listbox. Once you have read the RSS feed and put the data into your class then you can access this information any time.
Now in your MouseClick event handler you can access the SelectedItem of the listbox, cast it to your class, and then access the properties that you previously assigned, to assign to the richtextbox text, no need for either rssRead or the loop.
Optional stuff:
instead of MouseClick event, use SelectedIndexChanged
There are a bunch of rss feed reader nugets available, no need to make your own nvm you're using Syndication which is fine :)
Clean code
Unused variables x, y
Define variables subject and summary in the foreach instead of at the top
Better yet, don't use subject and summary variables at all since their values are already stored in item.Title.Text and item.Summary.Text
Have fun with C#!
You have this code:
private void listBox2_MouseClick(object sender, MouseEventArgs e)
{
var list = RSSreader.rssRead(tbxURL.Text);
foreach (Tuple<string, string> item in list)
{
if (item != listBox2.SelectedItem)
{
richTextBox1.Text = item.Item2.ToString();
}
}
}
You run through all the items saying: "If this is not the droid I'm looking for, I will add it to the RichTextBox". I think what you mean is: "If this IS the droid I'm looking for, I will add it to the RichTextBox.
That would be:
private void listBox2_MouseClick(object sender, MouseEventArgs e)
{
var list = RSSreader.rssRead(tbxURL.Text);
foreach (Tuple<string, string> item in list)
{
if (item == listBox2.SelectedItem) // Notice the equality operator
{
richTextBox1.Text = item.Item2.ToString();
}
}
}
I don't know if it's a typo on your part, but the equality operator is ==, not !=.
Your code would always show the last item in the list.
I can't update ComboBox that is linked to another ComboBox. I have one ComboBox that has countries and the other has cities. When I select a country, cityComboBox shows me the cities inside it, but when I change Country it still shows me the same cities. Here is my code
//method to get the cities
public IEnumerable<Ciudad> GetCP(int a) {
string SelectCP = "SELECT [ciudadID],[nombre] FROM [proyectoZoo].[dbo].[Ciudad] where [paisID]=" + a + "";
List<Ciudad> Ciudades = new List<Ciudad>();
foreach (IDataReader reader in this.Execute(SelectCP)) {
Ciudad ciudad = new Ciudad();
ciudad.ciudadID = reader.GetInt32(0);
ciudad.nombre = reader.GetString(1);
Ciudades.Add(ciudad);
}
return Ciudades;
}
Windows form:
IEnumerable<Country> Countries = server.GetCountries();
cmbPais.DataSource = Countries;
IEnumerable<Ciudad> Ciudades = server.GetCP((int)cmbPais.SelectedValue);
cmbCiudad.DataSource = Ciudades;
You need to add this code for the SelectedIndexChanged event handler of cmbPais
void cmbPais_SelectedIndexChanged(object sender, EventArgs e)
{
if(cmbPais.SelectedValue != null)
{
IEnumerable<Ciudad> Ciudades = server.GetCP((int)cmbPais.SelectedValue);
cmbCiudad.DataSource = Ciudades;
}
}
I am creating a CheckBoxList in a class file and am using an HTMLTextWriter to render the control.
I'm using the following code to store the selected values in a string:
string YrStr = "";
for (int i = 0; i < YrChkBox.Items.Count; i++)
{
if (YrChkBox.Items[i].Selected)
{
YrStr += YrChkBox.Items[i].Value + ";";
}
}
I stepped through the code and it doesn't seem to hit the inside of the if statement & the selected value attribute is false every time ... Anyone have an idea of how I can address this?
I populate it using the following:
YrChkBox.Items.Add(new ListItem("Item 1", "Item1"));
In your ASPX page you've got the list like this:
<asp:CheckBoxList ID="YrChkBox" runat="server"
onselectedindexchanged="YrChkBox_SelectedIndexChanged"></asp:CheckBoxList>
<asp:Button ID="button" runat="server" Text="Submit" />
In your code behind aspx.cs page, you have this:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
// Populate the CheckBoxList items only when it's not a postback.
YrChkBox.Items.Add(new ListItem("Item 1", "Item1"));
YrChkBox.Items.Add(new ListItem("Item 2", "Item2"));
}
}
protected void YrChkBox_SelectedIndexChanged(object sender, EventArgs e)
{
// Create the list to store.
List<String> YrStrList = new List<string>();
// Loop through each item.
foreach (ListItem item in YrChkBox.Items)
{
if (item.Selected)
{
// If the item is selected, add the value to the list.
YrStrList.Add(item.Value);
}
else
{
// Item is not selected, do something else.
}
}
// Join the string together using the ; delimiter.
String YrStr = String.Join(";", YrStrList.ToArray());
// Write to the page the value.
Response.Write(String.Concat("Selected Items: ", YrStr));
}
Ensure you use the if (!IsPostBack) { } condition because if you load it every page refresh, it's actually destroying the data.
Try something like this:
foreach (ListItem listItem in YrChkBox.Items)
{
if (listItem.Selected)
{
//do some work
}
else
{
//do something else
}
}
check boxlist selected values with seperator
string items = string.Empty;
foreach (ListItem i in CheckBoxList1.Items)
{
if (i.Selected == true)
{
items += i.Text + ",";
}
}
Response.Write("selected items"+ items);
An elegant way to implement this would be to make an extension method, like this:
public static class Extensions
{
public static List<string> GetSelectedItems(this CheckBoxList cbl)
{
var result = new List<string>();
foreach (ListItem item in cbl.Items)
if (item.Selected)
result.Add(item.Value);
return result;
}
}
I can then use something like this to compose a string will all values separated by ';':
string.Join(";", cbl.GetSelectedItems());
// Page.aspx //
// To count checklist item
int a = ChkMonth.Items.Count;
int count = 0;
for (var i = 0; i < a; i++)
{
if (ChkMonth.Items[i].Selected == true)
{
count++;
}
}
// Page.aspx.cs //
// To access checkbox list item's value //
string YrStrList = "";
foreach (ListItem listItem in ChkMonth.Items)
{
if (listItem.Selected)
{
YrStrList = YrStrList + "'" + listItem.Value + "'" + ",";
}
}
sMonthStr = YrStrList.ToString();
// aspx.cs
// Load CheckBoxList selected items into ListBox
int status = 1;
foreach (ListItem s in chklstStates.Items )
{
if (s.Selected == true)
{
if (ListBox1.Items.Count == 0)
{
ListBox1.Items.Add(s.Text);
}
else
{
foreach (ListItem list in ListBox1.Items)
{
if (list.Text == s.Text)
{
status = status * 0;
}
else
{
status = status * 1;
}
}
if (status == 0)
{ }
else
{
ListBox1.Items.Add(s.Text);
}
status = 1;
}
}
}
}
I use a ComboBox which is bound to a List<> of Entities. How can I add a "Not selected" entry to the combobox? Adding null to the list results in empty combobox.
If you're binding to IEnumerable list of entities you can certainly add your empty object manually.
For example
var qry = from c in Entities
select c;
var lst = qry.ToList();
var entity = new Entity();
entity.EntityId= -1;
entity.EntityDesc = "(All)";
lst.Insert(0, entity);
MyComboBox.DataSource = lst;
MyComboBox.DisplayMember = "EntityDesc"
MyComboBox.ValueMember = "EntityId"
You should use an empty string or other unique text pattern instead of null.
And then You can handle the Format event of the Combobox to intercept the <empty> and display an alternate text.
private void comboBox1_Format(object sender, ListControlConvertEventArgs e)
{
e.Value = FormatForCombobox(e.ListItem);
}
private string FormatForCombobox(object value)
{
string v = (string) value;
if (v == string.Empty)
v = "<no Selection>";
return v;
}