WPF list<t> sort - wpf

my first post here.
i have a list"<"frameworkelement> that i'm populating with a select process. each frameworkelement has a uid that holds its ZOrder.
i need to sort these by the ZOrder from lowest to highest. i can get this using a listbox and adding the Uid's like this:
//Add Object Uid's
ListBox lstTempOrder = new ListBox();
foreach(FrameworkElement feObject in MainWindow.Data.SelectedObjects)
{
lstTempOrder.Items.Add(feObject.Uid);
}
//Reorder from 0 to above of the ZIndexes
lstTempOrder.Items.SortDescriptions.Add(new System.ComponentModel.SortDescription("", System.ComponentModel.ListSortDirection.Ascending));
but i need to do this with a List"<"FrameWorkElement> and Sort.
Here is the code where i populate the List"<"T> (SelectedObjects and CopyObjectsCollections are List"<"FrameWorkElement>" lists.
foreach(FrameworkElement feObject in MainWindow.Data.SelectedObjects)
{
MainWindow.Data.CopyObjectsCollection.Add(feObject);
}
i've looked at CollectionViewSource and IComparer but i can't really make any sense of it.

I might have miss-read your question, but if you just want to sort your List<T>, then why don't you just use the LinQ OrderBy method?
MainWindow.Data.CopyObjectsCollection =
MainWindow.Data.CopyObjectsCollection.OrderBy(f => f.Uid).ToList();
If that sorts it the wrong way round for your requirements, then you can use this:
MainWindow.Data.CopyObjectsCollection =
MainWindow.Data.CopyObjectsCollection.OrderByDescending(f => f.Uid).ToList();
UPDATE >>>
OrderBy is a LinQ extension method. Add using System.Linq; at the top of your class to use it. f relates to an instance of your FrameworkElement object. The above lambda expression basically means 'sort using the Uid property values'.
UPDATE 2 >>>
The OrderBy method does not alter the original collection... that is why my example sets the collection to the result of the OrderBy method. See this basic example:
List<FrameworkElement> elements = new List<FrameworkElement>();
elements.Add(new FrameworkElement() { Uid = "Object1003-1" });
elements.Add(new FrameworkElement() { Uid = "Object1002-2" });
elements.Add(new FrameworkElement() { Uid = "Object1002-1" });
elements.Add(new FrameworkElement() { Uid = "Object1001-1" });
elements.Add(new FrameworkElement() { Uid = "Object1001-3" });
elements.Add(new FrameworkElement() { Uid = "Object1001-2" });
string result = string.Join(", ", elements.Select(f => f.Uid));
elements = elements.OrderBy(f => f.Uid).ToList();
string orderedResult = string.Join(", ", elements.Select(f => f.Uid));
By comparing the values of result and orderedResult you can see that this orders them perfectly.
UPDATE 3 (and hopefully the LAST one) >>>
Dude, you need to learn about Lambda expressions... take a look at the Lambda Expressions (C# Programming Guide) page at MSDN for more information.
elements = elements.OrderBy(f => f.Uid).ToList();
The f in this Lambda expression is declared in this expression before the '=>'. It is fairly standard to name these parameters with one letter like Exceptions, but we could name it anything:
elements = elements.OrderBy(frameworkElement => frameworkElement.Uid).ToList();

Related

How to not duplicate same item in a list dart?

I have created a listView and button and when I click the button it adds an item to listView.
The problem is I don't want actually to repeat the same item in the list.
I've tried the .contains method but it didn't work.
I want a good solution please,
There are different ways to achieve this:
1) Iterate the list and check if every element doesn't have the
properties you consider equal:
items = [Item(id: 1), Item(id: 2)];
newItem = Item(id: 2);
if (items.every((item) => item.id != newItem.id)) {
items.add(newItem);
}
2) Use contains() and override == operator (and override hashCode too)
in the object class with the properties you consider equal.
items = [Item(id: 1), Item(id: 2)];
newItem = Item(id: 2);
if (!items.contains(newItem)) {
items.add(newItem);
}
// inside Item class
#override
bool operator ==(other) {
return this.id == other.id;
}
#override
int get hashCode => id.hashCode;
3) Instead of List use Set, where each element can occur only once. Its default implementation is LinkedHashSet that keeps track of the order.
Instead of List, Use Set.
void main() {
Set<String> currencies = {'EUR', 'USD', 'JPY'};
currencies.add('EUR');
currencies.add('USD');
currencies.add('INR');
print(currencies);
}
output: {EUR, USD, JPY, INR} // unique items only
Reference: Set<E> class
Check if the List already contains the element before you add it:
https://api.flutter.dev/flutter/dart-core/List-class.html
if(!List.contains(element) { add }
The contains method checks for equality, not for reference, so it must work as long as you compare a similar element. If your code isn't working, please provide it to us. Thanks.
If your list contains custom objects you may need to override the equality operator in the custom class.
You could also use a Set instead of a List.

MVC ViewBag Two Dimentional Array - How to access elements from controller

I have a simple MVC C# controller with 2 dimention array.
ViewBag.states = new SelectList(db.states, "state_code", "state_zone");
If state_code = "FL", I want to get its state_zone value in the controller
I tried:
int newZone = ViewBag.states["FL"].state_zone
but I get error:
Cannot apply indexing with [] to an expression of type 'System.Web.Mvc.SelectList'
Any ideas?
Since ViewBag.states is dynamic property, you can't use indexer of SelectList against it because state_zone already stored inside Text property:
int newZone = ViewBag.states["FL"].state_zone;
Also this declaration seems possible but may throwing indexing error as described in comment:
var zone = ViewBag.states as SelectList;
int newZone = Convert.ToInt32(zone.Items[0].Text); // error: 'cannot apply indexing with [] to an expression of type 'System.Collections.IEnumerable'
To use SelectList item indexer inside ViewBag object, you need to convert it into SelectList first, then use LINQ methods to reveal its value:
var zone = ViewBag.states as SelectList;
int newZone = Convert.ToInt32(zone.Skip(n).First().Text); // n = any index number
// alternative:
int newZone = Convert.ToInt32(zone.Where(p => p.Value == "[any_value]").First().Text);
Similar issue:
Get a text item from an c# SelectList

Google Earth Engine: set Feature to FeatureCollection, but not a whole Array

I try to add a new Feature to the large Feature Collection, but with a function set() its override the whole list to each feature. But my purpose is to add each value from the array to the corresponding FeatureCollection. Can anybody help me?
var table = ee.FeatureCollection(ft:.....blablabla);
**//Create an Array from the property DN in the FeatureCollection:**
var propert = table.limit(100).aggregate_array('DN');
*// Values less than 1 will be set to 1, larger than 1== 0:*
var limit = ee.Array(propert).lt(1);
print(limit);
//Function, that add the list! of features (limit) to new property (Class) in the FeatureCollection ("table").
var addFeature = function(ar) {
return ar.set({Class: limit});
//Map throw the Featurecollection table
var areaAdded = table.limit(100).map(addArea);
};
So, if you can see, my code add the whole Array [limit] to each property in the FeatureCollection, not a first Value from the Array to the first property and so on...
Could anybody help me? thank you
If you have a smallish number of features, you can convert the feature collection to a list, convert the array to a list, zip() them together, map a function over the lists to set the property. Toy example:
var features = [
ee.Feature(ee.Geometry.Rectangle(30.01, 59.80, 30.59, 60.15), {name: 'Voronoi'}),
ee.Feature(ee.Geometry.Point(-73.96, 40.781), {name: 'Thiessen'}),
ee.Feature(ee.Geometry.Point(6.4806, 50.8012), {name: 'Dirichlet'})
];
var fromList = ee.FeatureCollection(features);
var array = ee.Array([2, 3, 5]);
var lists = fromList.toList(fromList.size()).zip(array.toList());
var features = ee.FeatureCollection(lists.map(function(l) {
return ee.Feature(ee.List(l).get(0)).set('foo', ee.List(l).get(1));
}));
print(features);

Underscore indexOf within a Collection

I've been looking already around for the answer with no luck.
Basically I am reviewing again the Addy Osmani guide to Backbone, and it seems I can't get through this code here.
var people = new Backbone.Collection;
people.comparator = function(a, b) {
return a.get('name') < b.get('name') ? -1 : 1;
};
var tom = new Backbone.Model({name: 'Tom'});
var rob = new Backbone.Model({name: 'Rob'});
var tim = new Backbone.Model({name: 'Tim'});
people.add(tom);
people.add(rob);
people.add(tim);
console.log(people.indexOf(rob) === 0); // true
console.log(people.indexOf(tim) === 1); // true
console.log(people.indexOf(tom) === 2); // true
I don't see how people.comparator can reorder the collection even though is not called anywhere, plus how comes that returning 1 or -1 can reorder it.
Or is it implicitly called once the Collection is created or indexOf is called on the Collection itself?
From the backbone documentation:
By default there is no comparator for a collection. If you define a
comparator, it will be used to maintain the collection in sorted
order. This means that as models are added, they are inserted at the
correct index in collection.models.
So every time you call people.add(...) the collection uses the comparator that you have set with people.comparator = function(a, b) { ... } to insert the model in an ordered position.

XDocument - get list of node values

I have a XDocument something like this:
<LookupList>
<ImageInfo1>
<FieldID>1057</FieldID>
<FieldName>Lookup_test</FieldName>
<LookupText>open</LookupText>
</ImageInfo1>
<ImageInfo1>
<FieldID>1057</FieldID>
<FieldName>Lookup_test</FieldName>
<LookupText>Waiting for input</LookupText>
</ImageInfo1>
<ImageInfo1>
<FieldID>1057</FieldID>
<FieldName>Lookup_NEW_NAME</FieldName>
<LookupText>Closed</LookupText>
</ImageInfo1>
</LookupList>
I want to get
number and values of unique FieldName(s) and
a list of LookupText for each FieldName.
Can someone give me a hint how to go about it?
First you need to know how to read the elements from your XDocument:
public void ReadXDocument(XDocument doc)
{
foreach (XElement el in doc.Descendants("ImageInfo1"))
{
string fieldid = el.Element("FieldID").Value;
string fieldName = el.Element("FieldName").Value;
string lookupText = el.Element("LookupText").Value;
}
Once you know that, using Linq to achieve your goal is relatively straight forward.
This should give you a list of distinct FieldNames:
List<String> distinctNames = doc.Descendants("ImageInfo1")
.Select(o => o.Element("FieldName").Value)
.Distinct().ToList();
And this should give you a collection of LookupText values for each FieldName
IEnumerable groups = doc.Descendants("ImageInfo1")
.GroupBy(o => o.Element("FieldName").Value)
.Select(o => new { Key = o.Key, Lookups = o.ToList() });
}

Resources