I've got my objects in PagedCollectionView bound to DataGrid and DataPager.
var pcView = new PagedCollectionView(ObservableCollection<Message>(messages));
How can I easily get items from current page in PagedCollectionView from my ViewModel? I wish there were something like this:
var messagesFromCurrentPage = pcView.CurrentPageItems; // error: no such a property
There are properties like SourceCollection, PageIndex and Count but I don't find them useful in this case. What am I missing here?
If you want to get select items you can just use Linq to do it.
var items = pcView.Where(i => i.SomeCondition == true);
Make sure you add a using statement for System.Linq.
Edit: Whenever I have a question as to what is really going on I just look at the code using Reflector (or ILSpy). In this case here is the relevant code inside GetEnumerator() which is how the Select or Where gets the items in the list:
List<object> list = new List<object>();
if (this.PageIndex < 0)
{
return list.GetEnumerator();
}
for (int i = this._pageSize * this.PageIndex; i < Math.Min(this._pageSize * (this.PageIndex + 1), this.InternalList.Count); i++)
{
list.Add(this.InternalList[i]);
}
return new NewItemAwareEnumerator(this, list.GetEnumerator(), this.CurrentAddItem);
So you can see how it is returning only the items in the current page from this code.
Related
I have a comboBox in XPages which is showing an hierarcal list of categories and values populates as a vector in SSJS.
I now want to apply a styleheet (bold) to the categories (i.e on only the categories of the generated option tags)
please note that I do not need a lesson in how stylesheets work. I need to know how to add a class or style to the categories in the outputted options tags
how can I do that?
thanks
Thomas
UPDATED MY QUESTION WITH A WORKING CLASS
Mimics a categorized view with 3 columns in a comboBox, category, label and value
public class Utils {
public static List<SelectItem> getGroupedComboboxOptions() {
try {
Database db = ExtLibUtil.getCurrentDatabase();
View vv = db.getView("ProdukterByCat");
Vector v = vv.getColumnValues(0);
List<SelectItem> groupedOptions = new ArrayList<SelectItem>();
SelectItemGroup group;
for (int i = 0; i < v.size(); i++) {
List<SelectItem> options = new ArrayList<SelectItem>();
group = new SelectItemGroup(v.get(i).toString());
ViewEntryCollection nvec = vv.getAllEntriesByKey(v.get(i), true);
ViewEntry entry = nvec.getFirstEntry();
while (entry != null) {
SelectItem option = new SelectItem(entry.getColumnValues().get(2).toString(),entry.getColumnValues().get(1).toString());
options.add(option);
entry = nvec.getNextEntry(entry);
}
group.setSelectItems(options.toArray(new SelectItem[options.size()]));
groupedOptions.add(group);
}
return groupedOptions;
} catch (NotesException e) {
e.printStackTrace();
}
return null;
}
}
A combobox in XPages is rendered using a HTML select tag. If you organise the options in optgroup's (see also Populating selectItems of the combobox (label, value) using a managed bean) you get some default styling out of the box. Example here.
You can even apply additional styling on them with standard CSS by targeting the optgroup. But support for that is limited: it doesn't work on an iPad for example.
If you want more control on how your dropdowns look, I'd suggest to use a plugin like Select2.
Summary:
I'm creating a simple application for practice, where the user can maintain and query a collection of Things. On the UI are several TextBoxes and ComboBoxes with which they can filter the collection.
The three buttons I'm concerned with are [Filter], [Random], and [All]. [Filter] applies the current filter options. [Random] applies the current filter options (if any), and then only shows one random entry from the filtered results. [All], as expected, shows the unfiltered collection.
To fully understand the background for the question, I'll provide the relevant code.
Here is where anything having to do with the CollectionViewSource (or any relevant code I'm posting) gets declared:
//Members
private ObservableCollection<Thing> _myDataCollection;
private CollectionViewSource _CVS;
private Thing _randomThing;
//Properties
public ObservableCollection<Thing> MyDataCollection
{
get { return _myDataCollection; }
set
{
if (_myDataCollection!= value)
{
_myDataCollection= value;
RaisePropertyChanged(() => MyDataCollection);
}
}
}
public CollectionViewSource CVS
{
get { return _CVS; }
set
{
if (_CVS != value)
{
_CVS = value;
RaisePropertyChanged(() => CVS);
}
}
}
public ICollectionView CVSView
{
get { return CVS.View; }
}
Here is where the CVS is initialized (in the window view-model's constructor). For now, the data collection is populated with a ton of random things (that's all that RandomizeData() does).
MyDataCollection = new ObservableCollection<Thing>();
RandomizeData();
CVS = new CollectionViewSource();
CVS.Source = MyDataCollection;
Here is the code for the [Filter] button's command:
//Clear any stale filter options and rebuild with the most current ones.
CVSView.Filter = null;
//IF THE FOLLOWING LINE IS UNCOMMENTED, THE ISSUE OCCURS.
//CVS.Filter -= new FilterEventHandler(SingleRandomFromCollectionFilter);
BuildCVSFilter();
The code for the [All] button literally just clears the filter:
CVSView.Filter = null;
The code for the [Random] button. I suspect the issue is coming from the handler added here.
//Clear any stale filter options and rebuild with the most current ones.
CVSView.Filter = null;
//IF THE FOLLOWING LINE IS UNCOMMENTED, THE ISSUE OCCURS.
//CVS.Filter -= new FilterEventHandler(SingleRandomFromCollectionFilter);
BuildCVSFilter();
//Only proceed if there are actually results in the filtered collection.
int resultsCount = CVSView.Cast<Thing>().Count();
if (resultsCount > 0)
{
//Point to a random thing in the filtered collection.
CVSView.MoveCurrentToPosition(random.Next(0, resultsCount));
_randomThing = CVSView.CurrentItem as Thing;
//Add another filter event that further constrains the collection to only contain the random thing.
CVS.Filter += new FilterEventHandler(SingleRandomFromCollectionFilter);
}
And here is the code for that BuildCVSFilter() I've been calling. I use this so that I can use multiple filters concurrently. The "FilterOption" strings are properties that are bound to the values of the UI controls.
if (!string.IsNullOrEmpty(FilterOption1))
{
CVS.Filter += new FilterEventHandler(Fitler1);
}
if (!string.IsNullOrEmpty(FilterOption2) && FilterOption2 != "ignore")
{
CVS.Filter += new FilterEventHandler(Fitler2);
}
if (!string.IsNullOrEmpty(FilterOption3))
{
CVS.Filter += new FilterEventHandler(Filter3);
}
Each filter that gets added this way only sets e.Accepted to false, if applicable, and leaves it alone if it's true.
Issue:
If I click on [Random] at all, it seems like the FilterEventHandler that gets added there does not go away. This makes it so that selecting [Filter] after [Random] won't work as expected, because it's only going to filter from the current collection of one thing. Additionally, selecting [Random] a second time seems to reuse the same random thing (instead of finding a new one). Interestingly enough, clicking [All] still works just fine. It shows everything.
When I go into those [Filter] and [Random] OnCommand methods and explicitly add a line to remove that SingleRandomFromCollectionFilter handler, everything works as expected.
Why would NameEntriesView.Filter = null; work to clear the filter on [All], but not on [Filter] or [Random]? Is there something about the CollectionViewSource and its implementation that I'm not fully understanding?
I am filling a listcontrol (Telerik for WinForms) by using the following code :
public static List<RadListDataItem> GetItems()
{
List<RadListDataItem> items = new List<RadListDataItem>();
for (int i = 1; i <= 10; i++)
{
RadListDataItem toadd = new RadListDataItem();
toadd.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText;
toadd.Text = "sssssssssss";
//toadd.Image.
string imagename = "MyProject.SuIcons.d" + i + ".JPG";
toadd.Image = new Bitmap(Assembly.GetExecutingAssembly().
GetManifestResourceStream(imagename));
items.Add(toadd);
}
return items;
}
but, only top portition of every item image is show in listcontrol, I mean I cant see the whole image associated with item in the list.
Would you help me please ?
You should set the AutoSizeItems property of the control to true in order to allow the visual items size themselves according to their content:
radListControl1.AutoSizeItems = true;
You can adjust the item size of the radListView. There is a property ItemSize that you can change in the designer view. Or if you want to do it programmatically, you can do something like this.
radListView1.ItemSize = new System.Drawing.Size(200, 400);
The first parameter is the width and the second is the height.
With normal winform controls I would do something like this:
ListView.SelectedListViewItemCollection col = listView1.SelectedItems;
foreach (ListViewItem item in col)
{
label8.Text = item.SubItems[1].Text;
label9.Text = item.SubItems[3].Text;
}
but I cant seem to create the samething with telerik radlistview, any ideas?
You should be able to do something similar with radlistview. The class you need to use is Telerik.WinControls.UI.ListViewDataItem.
Telerik.WinControls.UI.ListViewSelectedItemCollection col = listView1.SelectedItems
foreach (ListViewDataItem item in col)
{
label8.Text = item[1].ToString();
label9.Text = item[3].ToString();
}
I'm not sure if the ToString() is necessary. I tried it without the ToString(), and it worked fine for me, but my objects are strings.
Following Telerik Documentation
You can choose one of three methods to get or set values in subitems of RadListView:
- by using the column index
- by using the column name
- by using a column reference
Examples:
item[0] = "CellValue1";
item["Column2"] = "CellValue2";
item[radListView1.Columns[2]] = "CellValue3";
I have a DataTable that is coming from a Web Service, which I need to bind to a ComboBox. I have not grokked doing binding in XAML yet so this question is about binding in code instead. So far I have tried
cboManager.DataContext = Slurp.DistrictManagerSelect().DefaultView;
cboManager.DisplayMemberPath = "Name";
cboManager.SelectedValuePath = "NameListId";
cboManager.SetBinding(ComboBox.ItemsSourceProperty, new Binding());
And I have tried
DataTable tbl = new DataTable();
tbl = Slurp.DistrictManagerSelect();
cboManager.ItemsSource = ((IListSource)tbl).GetList();
cboManager.DisplayMemberPath = "[Name]";
cboManager.SelectedValuePath = "[NameListId]";
DataContext = this;
In both cases I get the list of managers to show but when I select from the ComboBox I get [Name] and [NameListId] and not the values I am expecting. What am I doing wrong (other than not using XAML's DataBinding)?
Edit added after answers to my original post came in.
So (based on Rachel's response) try number three looks like this:
using (DataTable tbl = Slurp.DistrictManagerSelect())
{
List<ManagerList> list = new List<ManagerList>();
foreach (var row in tbl.Rows)
{
list.Add(new ManagerList
{
NameListId = (int)row[0],
Name = row[1].ToString()
});
}
}
Assuming I am doing what she meant the correct way I am no getting this error Cannot apply indexing with [] to an expression of type 'object'
Have you tried to just bind to the DataTable directly? Do you have columns Name and NameListId? Leave off the DataContext (you already assigned the ItemsSource).
DataTable tbl = Slurp.DistrictManagerSelect();
cboManager.ItemsSource = tbl;
cboManager.DisplayMemberPath = "Name";
cboManager.SelectedValuePath = "NameListId";
When you cast to the IListSource I suspect it is combining all the columns. If you want to bind to a list then you need to create items that have properties Name and NameListID.
I think that's because your ItemsSource is a DataTable, so each ComboBoxItem contains a DataContext of a DataRow, and the DataRow class doesn't have properties called Name or NameListId
Basically, you're trying to tell the ComboBox to display DataRow.Name, and set the value to DataRow.NameListId, both of which are not valid properties.
I usually prefer to parse data into objects, and bind the ItemsSource a List<MyObject> or ObservableCollection<MyObject>
foreach(DataRow row in tbl.Rows)
list.Add(new MyObject { Name = row[0].ToString(), NameListId = (int)row[1] });
cboManager.ItemsSource = list;