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.
Related
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();
I'am currently developing an WinRT app an need a ListView ordered by date and grouped by day. The ListView is bound to an ICollectionView in my ViewModel
public Windows.UI.Xaml.Data.ICollectionView GroupedData {
get
{
return cvSource.View;
}
}
private Windows.UI.Xaml.Data.CollectionViewSource cvSource;
In my XAML I can bind then the ListView to this property:
<ListView ItemsSource="{Binding GroupedData}"
Now I'am doing some calculations and Filtering on my basicData, which is stored in a List<>. After i've done this, the grouping happens via LINQ:
var result = from DataObject in basicData
group DataObject by DataObject.Date
into date_grp orderby date_grp.Key
select date_grp;
Finally I set the source of the CollectionView to this new result and fire OnPropertyChanged
cvSource.Source = result.ToList();
OnPropertyChanged("GroupdedData");
This is working as I expected, but the ListView now selects the first element every time I populate a new source. I got rid of this as described on Stackoverflow by sellmeadog
NowI like to manually select an item. This should be the previous selected item before the source of the CollectionView is changed. What is the best way to save this previous item, see if its in the newly created CollectionView, select it and scroll to it?
Best regards
For the selecting senario, add a new property to the ViewModel in and bind SelectedItem property of the ListView to it:
public Windows.UI.Xaml.Data.ICollectionView GroupedData {
get
{
return cvSource.View;
}
}
public YourObjectType CurrentItem {
get {
return this.currentItem;
}
set {
if (this.currentItem != value) {
this.currentItem = value;
this.OnPropertyChanged("CurrentItem");
}
}
}
private YourObjectType currentItem;
private Windows.UI.Xaml.Data.CollectionViewSource cvSource;
Then before setting the source, hold a reference to the current item
var current = this.CurrentItem;
cvSource.Source = result.ToList();
this.CurrentItem = current;
assuming that your DataObjects type overrides Equals method, ListView finds and selects it in the collection. If not, you may need to add code finding it's instance in the new collection and assign it to CurrentItem property.
But by selecting the item doesn't mean ListViewScrolls to it. You may need to call ListView.BringIntoView in order to scroll to the selected item.
You need ObservableComputations. Using this library you can code like this:
private INotifyCollectionChanged _groupedData
public INotifyCollectionChanged GroupedData =>
_groupedData = _groupedData ?? basicData.Grouping(dataObject => dataObject.Date)
.Selecting(date_grp => date_grp.Key);
GroupedData reflects all the changes in the basicData collection. Do not forget to add the implementation of the INotifyPropertyChanged interface to DataObject class, so that GroupedData collection reflects the changes in dataObject.Date property. GroupedData is a singleton instance so you do not lost item selection in the ListView.
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.
The Scenario
I have a UserControl which contains a couple of controls, one of which is a ComboBox. The UserControl is conatined with a Page.
The UserControl exposes a couple of dependency properties to allow the Items and SelectedValue of the ComboBox to be accessed. These are defined as follows:
public static readonly DependencyProperty SelectedValueProperty = DependencyProperty.Register("SelectedValue", typeof(int?), typeof(CustomComboBox), new FrameworkPropertyMetadata((int?)null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
public int? SelectedValue
{
get { return (int?)this.GetValue(SelectedValueProperty); }
set { this.SetValue(SelectedValueProperty, value); }
}
public static readonly DependencyProperty ItemsProperty = DependencyProperty.Register("Items", typeof(List<ComboItem>), typeof(CustomComboBox), new FrameworkPropertyMetadata((List<ComboItem>)new List<ComboItem>(), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
public List<ComboItem> Items
{
get { return (List<ComboItem>)this.GetValue(ItemsProperty); }
set { this.SetValue(ItemsProperty, value); }
}
These are binded to the ComboBox control as follows:
<ComboBox ItemsSource="{Binding Path=Items, ElementName=ThisControl}" DisplayMemberPath="Text" SelectedValuePath="ID" SelectedValue="{Binding Path=SelectedValue, ElementName=ThisControl, UpdateSourceTrigger=PropertyChanged}" />
Where the UserControl is named "ThisControl".
Also, in the above, ComboItem is a class which contains the definitions for each item, namely two properties called ID and Text. The idea here is that ID is the key that is stored in the database, and Text is the user friendly value that is displayed in the list.
When the Page containing the UserControl is created (using the Constructor), the ComboBox items list is populated with the following code:
MyComboBox.Items.Clear();
MyComboBox.Items.Add(new ComboItem() { ID = 1, Text = "One" });
MyComboBox.Items.Add(new ComboItem() { ID = 2, Text = "Two" });
Finally, the SelectedValue is binded to a class property via XML like so:
<c:CustomComboBox x:Name="MyComboBox" SelectedValue="{Binding Path=MyClassInstance.ItemID}" />
where the property ItemID is of type int. It is important to note that the class instance is set after the combo box items are populated.
The Problem
When the page is first shown, the initial selected value is not set correctly - it is an empty item selection. I can assure that the ItemID property is already set to a valid value (i.e. 1).
When an item is selected from the ComboBox, the binding does successfully set the ItemID property, and is correctly persisted to the database upon a 'save' function.
One strange behavior, which may help to identity the problem, is that if the window containing the Page is closed, and then re-opened. The ComboBox does get th correct initial value - and that is regardless of the ComboBox being set on first attempt, or otherwise.
So, the question is: Why is the initial value not shown the first time the page is displayed?
OK, I was doing some refactoring to improve how I populate the ComboBox Items and I seem to have stumbled across the solution...
The problem seems to be related to the following piece of code that populates the list items:
MyComboBox.Items.Clear();
MyComboBox.Items.Add(new ComboItem() { ID = 1, Text = "One" });
MyComboBox.Items.Add(new ComboItem() { ID = 2, Text = "Two" });
The solution is to directly set the Items property, rather than to clear it and populate it:
MyComboBox.Items = GetMyList();
Where GetMyList() is returning a List<ComboItem> type.
I am having a combobox and the data is assigned dynamically as follows
<combobox
name="clientbox"
itemsource={Binding},
displaymemberpath="ClientName"
selectedvaluepath="clientid" />
I am loading the client details from DB and setting them to a listbox and assigning to the combobox as follows.
clientbox.DataContext = <list>
I am able to see the data in the combox after run. This will select the 0th item, but I want to default select different item. How to do this?
clientbox.SelectedItem = ((ComboBoxItem)clientbox.Items[1]);
clientbox.Text = ((ComboBoxItem)clientbox.Items[1]).Content.ToString();
There are several possibilities:
Code-behind:
// Setting the 0-based index
clientBox.SelectedIndex = 1;
// Setting the item
clientBox.SelectedItem = activeClient;
// Setting the value (explanation follows..)
clientBox.SelectedValue = activeClientValue
Using the SelectedValue property you can define a property of the item which is used to fill the ComboBox. An example: You fill the ComboBox with items of a class Client which has the properties Id, Name and so on. If you select an item, the SelectedItem property will be an instance of the class Client. By setting the SelectedValuePath property of the ComboBox to Id the SelectedValue will always just contain the id of the selected client.
Binding:
Of course you can always use bindings.
<ComboBox x:Name="clientBox"
ItemsSource={Binding ClientList}, DisplayMemberPath = "Name"
SelectedValuePath="Id"
SelectedValue={Binding ActiveClient} />