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.
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 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 bind my combobox from entityframework and when I try to get value from my combobox by selecting value it gives back text like this {NameOfCompany = Name } How can i get only the value Name?
Thats the code in xaml
<ComboBox SelectionChanged="ComboFirma_SelectionChanged" Name="ComboFirma" Margin="109,10,10,0" Height="28" VerticalAlignment="Top">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Name="txbCombo" Text="{Binding NameOfCompany}"></TextBlock>
</DataTemplate>
</ComboBox.ItemTemplate>
And I bind it like this.
var query2 = from f in model.Firmas
select new
{
f.NameOfCompany
};
ComboFirma.ItemsSource = query2.ToList();
I tried something like this to gets the selected value but always i get an exception.
var str = (TextBox)ComboFirma.Template.FindName("txbCombo", ComboFirma);
lblCompanyNameShow.Content = str.SelectedText;
ComboBox.SelectedItem will be of a item type. So normally you would need to cast SelectedItem to type of item in your collection. Now, because, in your case it's anonymous type, it's more difficult I think easiest way to get NameOfCompany is to use dynamic
dynamic selectedItem = ComboFirma.SelectedItem;
var name = selectedItem.NameOfCompany;
or you can use SelectedValue/SelectedValuePath
<ComboBox Name="ComboFirma" ... SelectedValuePath="NameOfCompany">
and in code
var name = (string)ComboFirma.SelectedValue;
Try like this
TextBlock tb1 = (TextBlock)ComboFirma.SelectedItem;
lblCompanyNameShow.Content = str.SelectedText;
I am having trouble assigning the a combobox item by using an enum value that the combobox source is assigned to.
The XAML
<ComboBox HorizontalAlignment="Left"
x:Name="cmbName"
VerticalAlignment="Top"
Width="120" Margin="79,48,0,0">
<ComboBox.ItemsSource>
<CompositeCollection>
<ListBoxItem Content="Please Select"/>
<CollectionContainer Collection="{Binding Source={StaticResource Enum}}" />
</CompositeCollection>
</ComboBox.ItemsSource>
</ComboBox>
The C# that is trying to set the combobox to an item in the enum
// The problem, the assignment doesn't work.
cmbName.SelectedItem = Enum.value;
I can only set a item by using the combobox SelectedIndex
cmbName.SelectedIndex = 2;
But this is hardcoding the index so if the enum changes, so will the value.
So how can I set the combobox by the enum value?
Thanks
It's very hard to tell what your problem is because you haven't fully documented your scenario. As such, all that I can do is to show you how to do what you want. As I prefer to work with properties, I won't be using any Resources for this example, but I'm sure that you'll still be able to relate this solution to your problem.
So, first we have a test enum and some properties and some initialisation:
public enum TestEnum
{
None, One, Two, Three
}
private TestEnum enumInstance = TestEnum.None;
public TestEnum EnumInstance
{
get { return enumInstance; }
set { enumInstance = value; NotifyPropertyChanged("EnumInstance"); }
}
private ObservableCollection<TestEnum> enumCollection = new ObservableCollection<TestEnum>() { TestEnum.None, TestEnum.One, TestEnum.Two, TestEnum.Three };
public ObservableCollection<TestEnum> EnumCollection
{
get { return enumCollection; }
set { enumCollection = value; NotifyPropertyChanged("EnumCollection"); }
}
...
EnumCollection.Add(TestEnum.One);
EnumCollection.Add(TestEnum.Two);
EnumCollection.Add(TestEnum.Three);
EnumInstance = TestEnum.Three;
Then we have a ComboBox:
<ComboBox Name="ComboBox" ItemsSource="{Binding EnumCollection}"
SelectedItem="{Binding EnumInstance}" />
If you run the application, then at this point the selected ComboBoxItem should read Three. Because the ComboBox.SelectedItem is data bound to the EnumInstance property, setting...:
EnumInstance = TestEnum.Two;
... is roughly the same as:
ComboBox.SelectedItem = TestEnum.Two;
Both of these would select the Two value in the ComboBox. However, note this example:
EnumInstance = TestEnum.None;
Setting either the EnumInstance or the ComboBox.SelectedItem property to TestEnum.None would have no effect in the UI because there is no TestEnum.None value in the data bound collection.
I apologise that my answer was descriptive enough, however, the reason why I haven't set my enum as a property as Sheridan has described below is that I need an extra string value in my combo which you can see is "Please Select" and unfortunately, I cannot put this in the enum.
But Sheridan's method and logic is the way to go if you want to do this.
However, for my problem, I simply just used
ComboBox.SelectedValue = Enum.Value.ToString();
Thanks
I have a ListView bound to an instance of data
ObservalbeCollection<ActivityItem> ActivityItems
<ListView
x:Name="ActivityItemsList"
ItemsSource="{Binding ActivityItems}"
ItemTemplate="{StaticResource Herke80ItemTemplate}"
Header="{Binding DateFilterListBox.SelectedItem}" />
When I run a filter, I want to select the ListViewItem bound to the ActivityItem within the ListView, and change its visibility depending on the filter selected.
I was doing this by keeping another ObservableCollection instance, meaning the data instance was duplicated. I then removed or added items accordingly. This took up a lot of loading time. So I figured I'd try keep to one binding, and disable or enable the UI elements.
foreach (ActivityItem activityItem in ActivityItemsList.Items)
{
if (activityItem == null) continue;
var index = ActivityItemsList.Items.IndexOf(activityItem);
(ActivityItemsList.Items[index] as ListViewItem).Visibility = Visibility.Collapsed;
int startComparer = DateTime.Compare(activityItem.Start, selectedStartDate);
int endComparer = DateTime.Compare(selectedEndDate, activityItem.End);
if (OverdueToggleSwitch.IsOn)
{
(ActivityItemsList.Items[index] as ListViewItem).Visibility = Visibility.Visible;
}
else
{
if (startComparer >= 0 && endComparer >= 0)
{
(ActivityItemsList.Items[index] as ListViewItem).Visibility = Visibility.Visible;
}
}
}
ex is a NullReferenceException, due to the fact that the ListViewItem is not actually a ListViewItem but an ActivityItem.
What is an alternative or the correct way of doing this?
I think you have over complicated it. If you use Snoop you can see that when you bind a ListView to a collection via ItemSource it ends up populated with a collection of ListViewItems where each ListViewItem has two things.
a DataContext set to the data (e.g. ActivityItem)
a ContentPresenter filled with the controls defined in your DataTemplate
This means that in theory you can browse both collections
from x in listView.Items select x as ListViewItem
or
from x in listView.Items select x.DataContext as ActivityItem
However if you simply want a filtered list then can I suggest changing your binding,
<ListView
x:Name="ActivityItemsList"
ItemsSource="{Binding FilteredItems}"
and
public class MyViewModel :INotifyPropertyChanged
{
public IEnumerable<ActivityItem> AllItems {get;set;} //needs to NotifyPropertyChanged(FilteredItems)
public Func<ActivityItem, bool> Filter { get;set;} //needs to NotifyPropertyChanged(FilteredItems)
public IEnumerable<ActivityItem> FilteredItems { get { return from x in AllItems where Filter(x) select x; }}
}
If you are still struggling with performance issues then have a quick read through Bea Costa's series on TreeView performance part one, part two and part three. It might help you to get WPF doing all the hard work for you.