I am developing a app in windows phone 7. I have a list box with items of observable collection. Now i want to search into that list box items. I want filter the items which is typed in the Text Box. If i type 'a' mean the list box items should shows the items which is start with 'a'. If i type 'az' mean it should show the items start with 'az'.
public class SortingExampleViewModel : ReactiveObject
{
public string _SearchText = "";
public string SearchText
{
get { return _SearchText; }
set { this.RaiseAndSetIfChanged(x => x.SearchText, value); }
}
public static ObservableCollection<items> _sordtedList;
public ObservableCollection<items> sordtedList
{
get { return _sordtedList; }
set { this.RaiseAndSetIfChanged(x => x.sordtedList, value); }
}
public static ObservableCollection<items> _tempSordtedList;
public ObservableCollection<items> tempSordtedList
{
get { return _tempSordtedList; }
set { this.RaiseAndSetIfChanged(x => x.tempSordtedList, value); }
}
public ReactiveAsyncCommand ExecuteSearch { get; set; }
public SortingExampleViewModel()
{
ObservableCollection<items> myData = new ObservableCollection<items>()
{
new items(){firstName = "Vijay Dhas",age=27},
new items(){firstName = "Ramaraj",age=28},
new items(){firstName = "Arun",age=29},
new items(){firstName = "Prabhu",age=30},
new items(){firstName = "Pranesh",age=31},
new items(){firstName = "Testing",age=32}
};
sordtedList = new ObservableCollection<items>(from i in myData orderby i.firstName select i);
var canConfirm = this.WhenAny(x => x.SearchText, (search) => SearchMethod(search.Value));
ExecuteSearch = new ReactiveAsyncCommand(canConfirm, 0);
}
public Boolean SearchMethod(String searchValue)
{
var col = (ObservableCollection<items>)(sordtedList.Where(p => p.firstName.Contains(searchValue)));
foreach (items objTest in col)
{
tempSordtedList.Add(objTest);
}
sordtedList = tempSordtedList;
return true;
}
}
public class items
{
public string firstName { get; set; }
public int age { get; set; }
}
But here i am getting Error in this line:
var col = (ObservableCollection<items>)(sordtedList.Where(p => p.firstName.Contains(searchValue)));
It showing Unknown error.
Please help me to search in the listbox.
I got the solution.
public SortingExampleViewModel()
{
ObservableCollection<items> myData = new ObservableCollection<items>()
{
new items(){firstName = "Vijay Dhas",age=27},
new items(){firstName = "Ramaraj",age=28},
new items(){firstName = "Arun",age=29},
new items(){firstName = "Prabhu",age=30},
new items(){firstName = "Pranesh",age=31},
new items(){firstName = "Testing",age=32}
};
sordtedList = new ObservableCollection<items>(from i in myData orderby i.firstName select i);
temp = sordtedList;
var canConfirm = this.WhenAny(x => x.SearchText, (search) => SearchMethod(search.Value));
ExecuteSearch = new ReactiveAsyncCommand(canConfirm, 0);
}
public Boolean SearchMethod(String searchValue)
{
ObservableCollection<items> tempList = new ObservableCollection<items>();
tempList = temp;
tempSordtedList = new ObservableCollection<items>();
foreach (items items in tempList)
{
if (items.firstName.ToLower().StartsWith(searchValue.ToLower()))
{
tempSordtedList.Add(items);
}
}
sordtedList = tempSordtedList;
return true;
}
You are casting an IEnumerable (result of the Linq query) to an ObservableCollection.
Use this instead:
var col = sordtedList.Where(p => p.firstName.Contains(searchValue));
Since you only use the variable col to iterate over it, you do not need to cast it.
Related
I have one Packet like below,
var dataPacket = new Packet
{
Id = new Guid("2e08bd98-68eb-4358-8efb-9f2adedfb034"),
Results = new Result
{
ResultName = "ResultName1",
Instances = new List<Instance>
{
new Instance
{
InstanceName = "InstanceName1",
InstanceDatas = new List<InstanceData>
{
new InstanceData{Name = "N1", Value = "V1"},
new InstanceData{Name = "N2", Value = "V2"}
}
},
new Instance
{
InstanceName = "InstanceName2",
InstanceDatas = new List<InstanceData>
{
new InstanceData{Name = "N1", Value = "V3"},
new InstanceData{Name = "N2", Value = "V4"}
}
}
}
}
};
Here are the class structures,
public class Packet
{
public Guid Id { get; set; }
public Result Results { get; set; }
}
public class Result
{
public string ResultName { get; set; }
public List<Instance> Instances { get; set; }
}
public class Instance
{
public string InstanceName { get; set; }
public List<InstanceData> InstanceDatas { get; set; }
}
public class InstanceData
{
public string Name { get; set; }
public string Value { get; set; }
}
For above Packet I want to spilt this into 2 Packets based on InstanceData common Name
All N1 from InstanceName1 and InstanceName2 into one packet
All N2 from InstanceName1 and InstanceName2 into one packet
Packet1 should be like this,
var packet1 = new Packet
{
Id = new Guid("2e08bd98-68eb-4358-8efb-9f2adedfb034"),
Results = new Result
{
ResultName = "ResultName1",
Instances = new List<Instance>
{
new Instance
{
InstanceName = "InstanceName1",
InstanceDatas = new List<InstanceData>
{
new InstanceData{Name = "N1", Value = "V1"},
}
},
new Instance
{
InstanceName = "InstanceName2",
InstanceDatas = new List<InstanceData>
{
new InstanceData{Name = "N1", Value = "V3"},
}
}
}
}
};
and similarly packet2.
I have tried below, but this will split on InstanceData as well and giving 4 packets.
var packets = dataPacket.Results
.Instances
.SelectMany(x =>
x.InstanceDatas.Select(y => new Packet()
{
Id = dataPacket.Id,
Results = new Result()
{
ResultName = dataPacket.Results.ResultName,
Instances = new List<Instance>()
{
new Instance()
{
InstanceDatas = new List<InstanceData>() {y},
InstanceName = x.InstanceName
}
}
}
}));
You can write a helper method which finds the possible names as keys and iterate over the keys. Then you build new object instances for each key you are checking. The source code can look like this:
private static IList<Packet> SplitByName(Packet packet) {
IList<string> names = packet.Results.Instances
.SelectMany(it => it.InstanceDatas)
.Select(it => it.Name)
.Distinct()
.ToList();
IList<Packet> result = new List<Packet>();
foreach (string name in names)
{
List<Instance> newInstances = packet.Results.Instances
.Select(it => new Instance {
InstanceName = it.InstanceName,
InstanceDatas = it.InstanceDatas
.Where(it => it.Name == name)
.ToList()
})
.Where(it => it.InstanceDatas.Any())
.ToList();
Result newResult = new Result {
ResultName = packet.Results.ResultName,
Instances = newInstances
};
result.Add(new Packet {
Id = packet.Id,
Results = newResult
});
}
return result;
}
For each name you are filtering the InstanceData instances for each Instance object. Depending on your needs you might want to add .Where(it => it.InstanceData.Any()) so you don't have any "empty" instances.
So, here's the problem:
I have a list of products:
public class ProductWithFeatures
{
public string Name { get; set; }
public ICollection<Feature> Features { get; set; }
}
public class Feature
{
public int Id { get; set; }
public Feature(int Id)
{
this.Id = Id;
}
}
I need to filter the list, using Linq functions, so that the only remaining items are the products that have at least one feature from a list of given features.
This is what i wrote:
public class ProductListFilteringClass
{
public List<ProductWithFeatures> products;
public ProductListFilteringClass(List<ProductWithFeatures> list)
{
this.products = list;
}
public List<ProductWithFeatures> ProductsWithAtLeastOneFeatureFromTheList(ICollection<Feature> features)
{
Func<ProductWithFeatures, bool> doesItHaveTheFeatures = x =>
{
FeatureComparer comparer = new FeatureComparer();
bool b = x.Features.Any(y => features.Contains(y, comparer));
return b;
};
return products.Where(doesItHaveTheFeatures).ToList();
}
}
public class FeatureComparer : IEqualityComparer<Feature>
{
public bool Equals(Feature x, Feature y)
{
return x.Id == y.Id;
}
public int GetHashCode(Feature obj)
{
return obj.Id;
}
}
Problem is, when i try to run a test on this, it results the correct answer but it doesn't match. Here's the test:
[Fact]
public void CheckIfReturnProductsWithAtLeastOneFeatureFromTheListWorksCorrectly()
{
LinqHomework.Feature[] ids = new LinqHomework.Feature[6];
ids[0] = new LinqHomework.Feature(1);
ids[1] = new LinqHomework.Feature(3);
ids[2] = new LinqHomework.Feature(5);
ids[3] = new LinqHomework.Feature(7);
ids[4] = new LinqHomework.Feature(9);
ids[5] = new LinqHomework.Feature(11);
List<LinqHomework.ProductWithFeatures> list = new List<LinqHomework.ProductWithFeatures>();
LinqHomework.Feature[] featuresA = new LinqHomework.Feature[3];
featuresA[0] = new LinqHomework.Feature(0);
featuresA[1] = new LinqHomework.Feature(5);
featuresA[2] = new LinqHomework.Feature(2);
LinqHomework.ProductWithFeatures productA = new LinqHomework.ProductWithFeatures();
productA.Name = "a";
productA.Features = featuresA;
list.Add(productA);
LinqHomework.Feature[] featuresB = new LinqHomework.Feature[3];
featuresB[0] = new LinqHomework.Feature(1);
featuresB[1] = new LinqHomework.Feature(3);
featuresB[2] = new LinqHomework.Feature(7);
LinqHomework.ProductWithFeatures productB = new LinqHomework.ProductWithFeatures();
productB.Name = "b";
productB.Features = featuresB;
list.Add(productB);
LinqHomework.Feature[] featuresC = new LinqHomework.Feature[3];
featuresC[0] = new LinqHomework.Feature(10);
featuresC[1] = new LinqHomework.Feature(4);
featuresC[2] = new LinqHomework.Feature(8);
LinqHomework.ProductWithFeatures productC = new LinqHomework.ProductWithFeatures();
productC.Name = "c";
productC.Features = featuresC;
list.Add(productC);
LinqHomework.ProductListFilteringClass productList = new LinqHomework.ProductListFilteringClass(list);
List<LinqHomework.ProductWithFeatures> final = new List<LinqHomework.ProductWithFeatures>();
LinqHomework.Feature[] features1 = new LinqHomework.Feature[3];
features1[0] = new LinqHomework.Feature(0);
features1[1] = new LinqHomework.Feature(5);
features1[2] = new LinqHomework.Feature(2);
LinqHomework.ProductWithFeatures product1 = new LinqHomework.ProductWithFeatures();
product1.Name = "a";
product1.Features = features1;
final.Add(product1);
LinqHomework.Feature[] features2 = new LinqHomework.Feature[3];
features2[0] = new LinqHomework.Feature(1);
features2[1] = new LinqHomework.Feature(3);
features2[2] = new LinqHomework.Feature(7);
LinqHomework.ProductWithFeatures product2 = new LinqHomework.ProductWithFeatures();
product2.Name = "b";
product2.Features = features2;
final.Add(product2);
var x = new ProductComparer();
Assert.Equal(final, productList.ProductsWithAtLeastOneFeatureFromTheList(ids), x);
}
public class ProductComparer : IEqualityComparer<LinqHomework.ProductWithFeatures>
{
public bool Equals(ProductWithFeatures x, ProductWithFeatures y)
{
return x.Name == y.Name && x.Features == y.Features;
}
public int GetHashCode(ProductWithFeatures obj)
{
string toHash = obj.Name;
foreach (var feature in obj.Features)
toHash += feature.GetHashCode();
return toHash.GetHashCode();
}
}
And here's the result:
Result Message:
Assert.Equal() Failure
Expected: List<ProductWithFeatures> [ProductWithFeatures { Features = [...], Name = "a" }, ProductWithFeatures { Features = [...], Name = "b" }]
Actual: List<ProductWithFeatures> [ProductWithFeatures { Features = [...], Name = "a" }, ProductWithFeatures { Features = [...], Name = "b" }]
It's identical, but it doesn't match. How can i fix this?
I would be looking at this part of your equality check:
public bool Equals(ProductWithFeatures x, ProductWithFeatures y)
{
return x.Name == y.Name && x.Features == y.Features;
}
The name comparison will work fine, but you are using the == operator to compare two collections, which will give you a reference equality check (is this the same instance of the collection) when it looks like you are interested in the values. You could try x.Features.SequenceEquals(y.Features) if you are confident they will be in the same order. More on list equality here.
Your ProductComparer method is comparing Features without using your special FeatureComparer method.
Try
public class ProductComparer : IEqualityComparer<ProductWithFeatures>
{
FeatureComparer featureComparer = new FeatureComparer();
public bool Equals(ProductWithFeatures x, ProductWithFeatures y)
{
return x.Name == y.Name &&
System.Linq.Enumerable.SequenceEqual( x.Features , y.Features, featureComparer);
}
...
i want to write a C# function which returns "alamaba" when i pass "Montgomery".
2nd example: Sitka --> Alaska
here is the list of the example:
List<PopulationUSA> result = new List<PopulationUSA>();
PopulationUSA usa = new PopulationUSA("Population in USA", 316128839, new List<PopulationUSA>());
result.Add(usa);
PopulationUSA alabama = new PopulationUSA("Alabama", 4833722, new List<PopulationUSA>());
usa.Items.Add(alabama);
alabama.Items.Add(new PopulationUSA("Birmingham", 212113, null));
alabama.Items.Add(new PopulationUSA("Montgomery", 201332, null));
alabama.Items.Add(new PopulationUSA("Mobile", 194899, null));
PopulationUSA alaska = new PopulationUSA("Alaska", 735132, new List<PopulationUSA>());
usa.Items.Add(alaska);
alaska.Items.Add(new PopulationUSA("Juneau", 32660, null));
alaska.Items.Add(new PopulationUSA("Ketchikan", 8214, null));
alaska.Items.Add(new PopulationUSA("Sitka", 9020, null));
here is the class:
public class PopulationUSA
{
public PopulationUSA(string name, int value, List<PopulationUSA> items)
{
Name = name;
Value = value;
Items = items;
}
public string Name { get; set; }
public int Value { get; set; }
public List<PopulationUSA> Items { get; set; }
}
How can i do that?
Thanks
you can add this method to the PopulationUSA class
public string FindParentsOfGrandChildren(string _name)
{
List<PopulationUSA> parents = Items.Where(s => s.Items.Any(c => c.Name == _name)).ToList();
if (parents != null)
{
string listparents = string.Empty;
for (int i = 0; i < parents.Count; i++)
{
if (i == 0)
{
listparents += parents[i].Name;
}
else
{
listparents += ", " + parents[i].Name;
}
}
return listparents;
}
else
{
return "Not found";
}
}
then use it like this in your example:
string WhereDoIBelong = usa.FindParentsOfGrandChildren("Montgomery")
it would be much better as a recursive method, finding parents of any type (not just "grandchildren") but that is your work!
I'm working in c# with Windows form.
I've an item DataGridView named objGridView, used like this :
public partial class dlgDetailsObj : Form
{
public dlgDetailsObj(myInterface item)
{
InitializeComponent();
objGridView.DataSource = new BindingList<dlgItem>();
var t = new Task(() =>
{
List<dlgItem> listElements = new List<dlgItem>();
if (item is List<Person>)
{
List<Person> list = (List<Person>)item;
foreach (Person person in list)
{
listElements.Add(new dlgItem()
{
Name = person.Name,
Forname = person.Forname
});
}
}
else if (item is List<Compagny>)
{
List<Compagny> list = (List<Compagny>)item;
foreach (Compagny compagny in list)
{
listElements.Add(new dlgItem()
{
Compagny = compagny.Name
});
}
}
else
{
return;
}
foreach (dlgItem item in listElements)
{
objGridView.Invoke((MethodInvoker)delegate
{
int sel = objGridView.GetSelectedRowIndex();
((BindingList<dlgItem>)objGridView.DataSource).Add(item);
objGridView.SetSelectedRowIndex(sel);
});
}
});
t.Start();
}
}
internal class dlgItem
{
public string Name { get; set; }
public String Forname { get; set; }
public String Compagny { get; set; }
}
The class dlgDetailsObj is used to display a list of Persons/Companies and probably more object later.
My DataGridView has a DataSource filled of dlgItem. Actually all three fields are displayed, even if I only only one.
How can I define my code to display columns only if binded fields are not null ?
If you want to hide all empty columns you could iterate through the DataSource collection to determine whether the corresponding property has been set for any dlgItem object:
public dlgDetailsObj(myInterface item)
{
InitializeComponent();
objGridView.DataSource = new BindingList<dlgItem>();
var t = new Task(() =>
{
...
});
t.Start();
t.ContinueWith(task =>
{
bool displayNameColumn = false;
bool displayFornameColumn = false;
bool displayCompanyColumn = false;
foreach (dlgItem item in (BindingList<dlgItem>)objGridView.DataSource)
{
if (!string.IsNullOrEmpty(item.Name))
displayNameColumn = true;
if (!string.IsNullOrEmpty(item.Forname))
displayFornameColumn = true;
if (!string.IsNullOrEmpty(item.Compagny))
displayCompanyColumn = true;
}
objGridView.Columns[0].Visible = displayNameColumn;
objGridView.Columns[1].Visible = displayFornameColumn;
objGridView.Columns[2].Visible = displayCompanyColumn;
}, System.Threading.CancellationToken.None, TaskContinuationOptions.None, TaskScheduler.FromCurrentSynchronizationContext());
}
I have two lists: a list of countries and a list of jobs
public List<Countries> getSharedCountries(string brandName)
{
var items = SharedJobs.Where(a => a.BrandName == brandName);
var items2 = items.OrderBy(a => a.CountryCode);
Countries = new List<Countries>();
string Country = null;
foreach (var item in items2)
{
if (Country != item.CountryCode)
{
Country = item.CountryCode;
Countries.Add(new Countries() { CountryCode = item.CountryCode, JobIDs = getSharedJob(item.CountryCode) });
}
}
return Countries;
}
public void getSharedJob(string Country)
{
var items = SharedJobs.Where(a => a.CountryCode == Country);
JobNetDetails = new List<JobDetail>();
CareerBoardDetails = new List<JobDetail>();
JobSharkDetails = new List<JobDetail>();
JobServeDetails = new List<JobDetail>();
int AusCount = 0;
foreach (var item in items)
{
if (Country == "AUS")
{
AusCount++;
if (AusCount % 4 == 0)
{
JobNetDetails.Add(new JobDetail() { JobPageTitle = item.JobPageTitle, JobID = item.JobID, JobUrl = item.JobUrl });
}
else
{
JobServeDetails.Add(new JobDetail() { JobPageTitle = item.JobPageTitle, JobID = item.JobID, JobUrl = item.JobUrl });
}
}
}
}
On the line where I am accessing the method getSharedJob, it errors and gives me the error, cannot implicitly convert void to system.generic.List?
I am very confused as to why this is happening?
As the signature of your method states, public void getSharedJob(string Country) it's void, so it doesn't return anything, you should change it and return the list you wish.
Edit: As I read in the comments you need to return 4 Lists.
You have several options:
You can return an array of Lists;
You can return a List of Lists;
You can return your own class containing the 4 Lists.
Try below code which returns jobDetails from the method you are calling
public List<Countries> getSharedCountries(string brandName)
{
var items = SharedJobs.Where(a => a.BrandName == brandName);
var items2 = items.OrderBy(a => a.CountryCode);
Countries = new List<Countries>();
string Country = null;
foreach (var item in items2)
{
if (Country != item.CountryCode)
{
Country = item.CountryCode;
foreach (var jobDetail in getSharedJob(item.CountryCode))
{
Countries.Add(new Countries() { CountryCode = item.CountryCode, JobIDs = jobDetail.JobID });
}
}
}
return Countries;
}
public List<JobDetail> getSharedJob(string Country)
{
var items = SharedJobs.Where(a => a.CountryCode == Country);
JobNetDetails = new List<JobDetail>();
CareerBoardDetails = new List<JobDetail>();
JobSharkDetails = new List<JobDetail>();
JobServeDetails = new List<JobDetail>();
int AusCount = 0;
foreach (var item in items)
{
if (Country == "AUS")
{
AusCount++;
if (AusCount % 4 == 0)
{
JobNetDetails.Add(new JobDetail() { JobPageTitle = item.JobPageTitle, JobID = item.JobID, JobUrl = item.JobUrl });
}
else
{
JobServeDetails.Add(new JobDetail() { JobPageTitle = item.JobPageTitle, JobID = item.JobID, JobUrl = item.JobUrl });
}
}
}
return JobServeDetails;
}
Your method signature says take a string variable and return nothing (void).
public void getSharedJob(string country)
JobIDs is expecting a value
JobIDs = getSharedJob(item.CountryCode)
so you need to return a value which matches the JobIDs type which I assume is a List of ints or a List of JobDetails.