Can't acces Sort property in a telerik:RadComboBox - c#

I have a Telerik ComboBox :
<telerik:RadComboBox Grid.Row="0" Grid.Column="1" VerticalAlignment="Center" IsReadOnly="True" SelectedIndex="0" x:Name="CbBoxUltra" SelectionChanged="CbBoxUltra_SelectionChanged" MinWidth="100"/>
I'm doing a "for each" loop to store items into it :
foreach (var ultra in line2)
{
...
if (deviceType != null && !String.IsNullOrEmpty(vehicleName) && vehicleName != "null" && deviceType == "ultra")
{
_listUltra.Add(new UltraModel { Id = Convert.ToInt32(idUltra), Name = nameUltra, NameVehicle = vehicleName });
CbBoxUltra.Items.Add(vehicleName);
}
}
I want to sort the items in my ComboBox (from a to z for exemple).
So I tried to do what's in the doc : Telerik's sorting
But in the .xaml, i can't acces the property "Sort", like I do with "VerticalAlignment" for example, and i can't access the property in the .xaml.cs neither :
CbBoxUltra.Items.Sort(); //It doesn't match anything here
I just can acces .SortDescription, but it's not what I'm searching for...

From what I gathered from Telerik's documentation, the Sort property is available only for ASP.NET RadComboBox Control (server-side), and not for WPF RadComboBox Control.
That given, there are two most common ways to proceed.
I. Take advantage of the existing WPF implementation
RadComboBox.Items property is actually inherited from ItemsControl. It is of type ItemCollection, which implements ICollectionView, and supports sorting via SortDescriptions collection. So if you want to sort by property values, you can simply add appropriate items to that collection:
CbBoxUltra.Items.SortDescriptions.Add(new SortDescription
{
PropertyName = "XXX",
Direction = ListSortDirection.Descending
});
CbBoxUltra.Items.SortDescriptions.Add(new SortDescription
{
PropertyName = "YYY",
Direction = ListSortDirection.Ascending
});
This code will cause the items to be sorted first by the XXX property in descending order, then by YYY property in ascending order. However if your sorting logic requires more than just referencing item property values, you can add a single sort description, leaving out the PropertyName:
CbBoxUltra.Items.SortDescriptions.Add(new SortDescription
{
Direction = ListSortDirection.Descending
});
This will cause the sorting mechanism to sort using the default comparer for your item type. In order to apply custom logic, make sure your items implement IComparable<T> interface. Ddefault comparer for string sorts in lexical order.
II. Pre-sort items before adding
This approach is somewhat easier provided you add items only once. Here's code excerpt:
foreach (var ultra in line2.OrderByDescending(...))
{
...
}
Note that in case you'll be adding items multiple times (e.g. upon user input), this will get much trickier since you'll have to manually insert items at proper indexes.

Related

foreach Certain item is in a ListBox - Winform, C#

I would like to know how I could find the amount of times a certain item appears in a listbox
foreach (string Item in listBox1.Items)
{
Console.WriteLine("1 Item");
}
Console.ReadLine();
Unfortunately, that cycles through the entire listBox. I only want a certain Item.
Assuming that listBox1.Items : List<string> or string[] ...
Option 1: listBox1.Items.Count(item => item == "YourCertainItem");
You could use Linq
Option 2: listBox1.Items.Where(item => item == "YourCertainItem").Count();
It would depend on the type of data you have bound to the ListBox and the types unique identifer (or the property you want to use for comparison).
For example, if you have bound a list of String to the Listbox, you could use
var result = listBox.Items.OfType<String>().Count(x=>x == valueToSearch);
Instead, if you have bound a Collection of Person Types to the ListBox, where Person.Id is the property you want to use for comparison, you could use
var result = listBox1.Items.OfType<Person>().Count(x=>x.Id == personToSearch.Id);
You need to begin by defining what would be the property you would compare the items in the ListBox by, after which you could use Linq as shown in the examples above.

Telerik RadListBox - how to default select some items?

I'm using a Telerik RadListBox (multi-select) in a Silverlight/C# application. First they wanted all items in the list to be selected by default. Ok, no problem:
RadListBox.SelectAllCommand.Execute(null, listboxname);
But now, one of the four items needs to be not selected by default, the other three selected. I've searched and searched for a code sample, fruitlessly. How can I accomplish this seemingly simple task?
Since the SelectedItems property of a RadListBox is of type IList, it is possible to still add items to that list instead of explicitly setting SelectedItems equal to another list.
For example, this will select all names not equal to 'Bobby' by default.
XAML:
<Grid>
<telerik:RadListBox x:Name="ListBox"
SelectionMode="Multiple"/>
</Grid>
Code-Behind:
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
IList<string> names = new List<string>();
names.Add("Alexander");
names.Add("Bobby");
names.Add("Chris");
names.Add("Dean");
ListBox.ItemsSource = names;
foreach (var name in names.Where(x => x != "Bobby"))
{
ListBox.SelectedItems.Add(name);
}
}
}

ListView binding cast items to ListViewItem

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.

Retrieve DataItem from RepeaterItem after databinding (during an event handler)

I'm trying to find a way to to do something that I think must be possible but I'm just missing the point on - so hopefully someone can give me a bit of a nudge :)
I'm utilising databinding in ASP.NET (viewstate turned off - so using controlstate for a few things here and there) to render a repeater (repeaterPriceClasses) that has a repeater within each itemtemplate (repeaterPriceBands). Basically this renders a table out of some text and a dropdownlist in each cell.
I'm trying to find a way to enumerate the repeaterOuter inside the event handler of a button to give me a list of all of the originally bound elements that have now got a dropdownlist with a value of >0, along with what that value is.
public Dictionary<Price, int> SelectedPrices
{
get
{
var sel = new Dictionary<Price, int>();
foreach(RepeaterItem itemClass in repeaterPriceClasses.Items)
{
var repeaterPriceBands = itemClass.FindControl("repeaterPriceBands") as Repeater;
foreach(RepeaterItem itemBand in repeaterPriceBands.Items)
{
var context = (Price)itemBand.DataItem;
var listQty = itemBand.FindControl("listQty") as DropDownList;
if(listQty.SelectedValue.ToInt32() > 0)
{
sel.Add(context, listQty.SelectedValue.ToInt32());
}
}
}
return sel;
}
}
Now this fails because the itemBand.DataItem is always null after databinding has finished.
What technique should I use to get around this?
Hidden field with primary keys in it
(not ideal as can be abused and adds
weight to the page)
Lookup from
original cached data based on indexes
(just seems wrong)
or something
else/better...?
EDIT: Is there any more information that I could provide to help this get answered?
You can try adding extra attributes to your HTML elements in the ItemDataBound event when DataItem is available.
ddlSomething.Attributes["Attribute1"] = dataItemObject.PropertyName;
[Edit]
Apart from using attributes, you can render some array containing JSON objects like this, for each row.
var repeaterItemAttributes = [ { Prop1: val1, Prop2: val2, ... }, { ... }, ... ]
So, by using this, you won't have to render the attributes, and your code will be XHTML compliant too (tho its not required). You can then loop through the object array and read any property you like. You can also apply the light encryption you were talking about to the property values.
[/Edit]

WPF: SelectedItems with duplicate object references

So lets say I have these classes:
public class Person
{
public string Name { get; set; }
}
public class PersonCollection : ObservableCollection<Person> { }
And lets say I have a ListView whose ItemsSource is bound to a PersonCollection. Now lets say I have this code:
public void AddPeople()
{
Person p = new Person() { Name = "Someone" };
MyPersonCollection.Add(p);
MyPersonCollection.Add(p);
MyPersonCollection.Add(p);
}
So now I have a ListView with three items in which all three items are references to the SAME object. So now I select lets say items with index 0 and 2 in the ListView.
The ListView.SelectedItems property will say I have ONE item selected since both visually selected items are the SAME object.
So how can I get the visually selected items so I can remove the items at indices 0 and 2, without removing the item at index 1?
In WinForms there is the ListBox.SelectedIndices property that would be useful here, but we don't have that in WPF, unfortunately...
You could iterate through the ListViewItems using ItemContainerGenerator.ContainerFromIndex, check ListViewItem.IsSelected and then remove them by index. However, this doesn't play well with virtualization because ContainerFromIndex could return null if you scroll away from the item and it gets virtualized.
The code would look something like this:
for(int ixPerson = myListView.Items.Count - 1; ixPerson >= 0; ixPerson--)
{
ListViewItem personItem = myListView.ItemContainerGenerator.ContainerFromIndex(ixPerson);
if (personItem.IsSelected)
{
mySourcePersonCollection.RemoveAt(ixPerson);
}
}
There are cases where this makes sense, adding people to a queue where appearing more than once is desirable for instance. For this case it seems like WPF is designed poorly. Is it possible to manually iterate between all items in the collection and check their selection state?
I think there's something wrong with your model! Whatever it is you are trying to achieve, I would try and find a more robust way of doing it.

Categories

Resources