when i use this code "var z = comboBox.Items[1].ToString();" and then show z in "MessageBox" i get this message "DataMdellayer.custumer" but i want text of item 1
<ComboBox x:Name="comboBox" HorizontalAlignment="Left" Margin="57,63,0,0" VerticalAlignment="Top" Width="120"/>
and
comboBox.ItemsSource = database.Customers.ToList();
comboBox.DisplayMemberPath = "CustomerSay";
comboBox.SelectedValuePath = "CustomerID ";
You are using CustomerSay property of Customers to show the value.
When you say:
var z = comboBox.Items[1].ToString();
You are converting a Costumer to string
But, considering that you want that costumer's CostumerSay property, you have to look for it.
So you must cast your ComboBoxItem to Costumer
(Customer)comboBox.Items[1]
And then look for the property
var z = ((Customer)comboBox.Items[1]).CustomerSay
1- You can cast your item to the data source object (customer) as #Marko said.
2- Use MVVM and bind your combobox to a ViewModel property. WPF has strong binding system to implement MVVM.
3- You can override ToString method of Customer class:
public class Customer
{
public override string ToString()
{
return CustomerSay;
}
}
I prefer the second solution, but if you don't want to use MVVM pattern #Marko's solution is better.
The index of item one starts at zero in c# so change your code like below to get the item one
var z = comboBox.Items[0].ToString();
Related
I have the following observable collection called SalesOrderCollection
private static ObservableCollection<SalesOrder> _salesOrderCollection = new ObservableCollection<SalesOrder>();
public static ObservableCollection<SalesOrder> SalesOrderCollection
{
get { return _salesOrderCollection; }
set
{
_salesOrderCollection = value;
}
}
I am assigning values like this:
SalesOrder order = new SalesOrder();
order.ItemSubTotal = 234;
order.TotalTaxes = 12;
order.TOTAL = 12345;
SalesOrderCollection.Add(order);
In the view, I am setting it like this to the label:
<Label Content="{Binding Path=TOTAL, UpdateSourceTrigger =PropertyChanged}"/>
However the label is empty. Any suggestions as to what I am doing wrong here ?
First of all, you are binding incorrectly - the label should not be bound to a specific item in a collection. Instead you should use a list control to show the contents of the ObesrvableCollection, then bind the selected item in the list control to a property on the viewmodel. Then the label should also be bound to the same property which contains the selected object.
If you insist on doing indexed binding to a specific item in the ObservableCollection then this syntax should do it for you:
<Label Content="{Binding Path=SalesOrderCollection[0].TOTAL}"/>
Here is an example.
Just another pointer: I'm not sure why you've made your SalesOrderCollection property static - this looks like the start of some potentially smelly code.
I'm having trouble accessing the ID of a model I am adding to a ComboBox. At the moment I have a model, a preset, that contains an ID and Text. I create a list of presets through OleDB and then filter the list down before adding the contents to a ComboBox. Here is the code that does this;
var ps = new PresetService();
List<PresetModel> presetList = ps.HandleGetPresets();
List<PresetModel> filteredList = presetList.Where(filteredPreset => filteredPreset.PresetReferenceFoxPro == 3).ToList();
try
{
foreach (PresetModel preset in filteredList)
{
presetComboBox.Items.Add(preset.PresetText);
}
}
catch (Exception ex)
{
var hEs = new HandleExceptionService();
hEs.HandleException(ex.ToString());
return false;
}
Here you can see that I am adding the preset's text to the ComboBox. The issue comes however when someone wants to add a Company using one of the presets. In this case I am actually not interested in the text, I just want to add the preset's ID to the database against a company instead.
Using SelectedItem is not allowing me to access the ID, it returns a null exception. This is what I've triedl
var selectedPreset = presetComboBox.SelectedItem as PresetModel;
var presetIDToAdd = selectedPreset.PresetID;
I assume that this does not work because I have simply added the preset's Text value to the ComboBox and not it's ID. How can I add preset to a ComboBox, only display it's text but access it's ID when needed?
The problem here is that you are adding the PresetText to the ComboBox, not the PresetModel itself:
presetComboBox.Items.Add(preset.PresetText);
On top of that, you are then trying to cast the SelectedItem to a PresetModel, but it's actually the PresetText.
I would suggest using the following method.
Firstly, add the whole object to the ComboBox, like this:
presetComboBox.Items.Add(preset);
You can then define an ItemTemplate on your ComboBox to display the PresetText, or, to make things easier, just set the DisplayMemberPath:
<ComboBox ...
DisplayMemberPath="PresetText"/>
This will allow you to cast the SelectedItem to a PresetModel, but also still displaying the PresetText property in the ComboBox.
I'm using WPF and the timer doesn't allow to use int for interval. Instead, it asks for TimeSpan
timer1.Interval = TimeSpan.FromMilliseconds(Convert.ToDouble(comboBox1.SelectedItem));
So I changed my code to this but at runtime it gives me an InvalidCastException, saying that the object cannot be converted from System.Windows.Controls.ComboboxItem to System.IConvertible.
How can I solve this?
You should use this
Convert.ToDouble(comboBox1.SelectedText)
The comboBox1.SelectedItem corresponds to the selected item of the ComboBox control and not with the text of it, which is that you want.
Specifically, the SelectedText property of a CombBox control
Gets or sets the text that is selected in the editable portion of a ComboBox.
as it is stated here.
Update
Please use this one:
((ComboBoxItem)comboBox1.SelectedItem).Content.ToString();
Or in two steps:
ComboBoxItem item = (ComboBoxItem)comboBox1.SelectedItem;
timer1.Interval = TimeSpan.FromMilliseconds(Convert.ToDouble(item.Content.ToString()));
For more information about the ComboBoxItem class, please have a look here.
It appears that you are adding ComboBoxItems directly to your ComboBox.
A cleaner and safer approach than parsing strings would be to continue binding to SelectedItem, but to also bind the ItemsSource to a collection of integers.
Then use the ItemTemplate property of the ComboBox to define how to render the integers if you are not satisfied with the default ToString() rendering.
<ComboBox ItemsSource="{Binding Intervals}" SelectedItem="{SelectedInterval}">
<ComboBox.ItemTemplate>
<DataTemplate TargetType="{x:Type Int64}">
<TextBlock Text="{Binding}" Background="Red"/>
</DataTemplate>
</ComboBox.ItemTemplate>
<ComboBox>
With properties looking something like this:
public int SelectedInterval {get;set;}
public List<int> Intervals {
get {
var lst = new List<int>();
for(var i = 1000; i <= 10000; i += 500)
{
lst.Add(i);
}
return lst;
}
}
Now you have strongly type properties that you can manipulate without parsing.
I'm using SubSonic 2.2 for my DAL and extended one of my classes with a calculated property that returns a string containing another property with indenting based on the level of the outline at which the item occurs. The code for the property is below. The problem is that when I try to use this property as the DisplayMember for a ListBox control on a form (the reason I wrote it in the first place) it won't work. The ListBox reverts to displaying the ID property which is set as the ValueMember. To test that the property was working I looped through the collection of objects that I was populating the ListBox with and, using MessageBox.Show(obj.property), confirmed that it was indeed returning the value I'm looking for. Am I missing something or should this work? btw - There may be a better way to do the indenting but that's not what I'm after at the moment, thanks!
Code follows:
public partial class InteriorsCategory : ActiveRecord, IActiveRecord
{
public string ListDisplay
{
get
{
string returnValue = "";
for (int i = 1; i < this.SpecLevel; i++)
{
returnValue += " ";
}
returnValue += this.CategoryName;
return returnValue;
}
}
}
<>
I definitely get data in my collection and the binding I'm doing is exactly the same as yours (binding code posted below). The return value of the ListDisplay property that I'm using is a string concatenation of two values in the object. Think of it as a "full name" property that concatenates the FirstName a space and the LastName properties into a single string which it returns. I am trying to bind the ListDisplay property to the DisplayMember property of the listbox, but all that shows in the listbox is the Id field which I am binding to the ValueMember.
private void FillCategories()
{
lstPackageCategories.DataSource = new InteriorsCategoryCollection().Load();
lstPackageCategories.DisplayMember = "CategoryName";
lstPackageCategories.ValueMember = "Id";
((InteriorsCategoryCollection)(lstPackageCategories.DataSource)).Sort("SpecSection", true);
lstPackageCategories.SelectedItem = lstPackageCategories.Items[0];
currentCategory = (InteriorsCategory)lstPackageCategories.SelectedItem;
RefreshAvailableItems();
}
If your able to see your data in the collection, then it sounds like there is a problem on the binding of your ListBox. Here is an example of how I bind a ListBox using a SubSonic collection of values.
ISOCountryCodeCollection countrys =
new ISOCountryCodeCollection().OrderByAsc(ISOCountryCode.Columns.Country).Load();
Country.DataSource = countrys;
Country.DataValueField = "ThreeChar";
Country.DataTextField = "Country";
Country.DataBind();
In the example above, I'm binding the 3 character country code to the "DataValueField" and the full country name to the "DataTextField".
I'm having trouble figuring out how to add items to a ListBox in WinForms.
I have tried:
list.DisplayMember = "clan";
list.ValueMember = sifOsoba;
How can I add ValueMember to the list with an int value and some text for the DisplayMember?
list.Items.add(?)
Btw. I can't use ListBoxItem for any reasons.
ListBoxItem is a WPF class, NOT a WinForms class.
For WPF, use ListBoxItem.
For WinForms, the item is a Object type, so use one of these:
1. Provide your own ToString() method for the Object type.
2. Use databinding with DisplayMemeber and ValueMember (see Kelsey's answer)
list.Items.add(new ListBoxItem("name", "value"));
The internal (default) data structure of the ListBox is the ListBoxItem.
In WinForms, ValueMember and DisplayMember are used when data-binding the list. If you're not data-binding, then you can add any arbitrary object as a ListItem.
The catch to that is that, in order to display the item, ToString() will be called on it. Thus, it is highly recommended that you only add objects to the ListBox where calling ToString() will result in meaningful output.
You might want to checkout this SO question:
C# - WinForms - What is the proper way to load up a ListBox?
DisplayMember and ValueMember are mostly only useful if you're databinding to objects that have those properties defined. You would then need to add an instance of that object.
e.g.:
public class MyObject
{
public string clan { get; set; }
public int sifOsoba { get; set; }
public MyObject(string aClan, int aSif0soba)
{
this.clan = aClan;
this.sif0soba = aSif0soba;
}
public override string ToString() { return this.clan; }
}
....
list.Items.Add(new MyObject("hello", 5));
If you're binding it manually then you can use the example provided by goggles
The way I do this - using the format Event
MyClass c = new MyClass();
listBox1.Items.Add(c);
private void listBox1_Format(object sender, ListControlConvertEventArgs e)
{
if(e.ListItem is MyClass)
{
e.Value = ((MyClass)e.ListItem).ToString();
}
else
{
e.Value = "Unknown item added";
}
}
e.Value being the Display Text
Then you can attempt to cast the SelectedItem to MyClass to get access to anything you had in there.
Also note, you can use anything (that inherits from object anyway(which is pretty much everything)) in the Items Collection.
If you just want to add a string to it, the simple answer is:
ListBox.Items.Add("some text");
You have to create an item of type ListBoxItem and add that to the Items collection:
list.Items.add( new ListBoxItem("clan", "sifOsoba"));
If you are adding integers, as you say in your question, this will add 50 (from 1 to 50):
for (int x = 1; x <= 50; x++)
{
list.Items.Add(x);
}
You do not need to set DisplayMember and ValueMember unless you are adding objects that have specific properties that you want to display to the user. In your example:
listbox1.Items.Add(new { clan = "Foo", sifOsoba = 1234 });