Linq join two objects to match customer selected records - c#

I have two List T objects. One is a list of forums available and the other the forums the user has selected. This is executing during a jquery ajax call and will be populating a listbox.
The purpose is that I want to flag the forums the user has subscribed to with "selected" which will of course render in the html listbox as a highlighted row.
I started to write this query and stopped short.
var result = (from exf in ExtForum
join custfrm in customer.ExternalForums on
exf.Id equals custfrm.Id
select new { id=exf.Id, name=exf.ForumName, isSelected=(true ? "selected" : "") })
.ToList();
This will only return the forums that match. What I need is a left outer query but in thinking about that I don't think that is correct either. Well it is sort of correct as it would return all available forums but now I am back to square one of figuring out how I would flag my matches.
My approach which is open to improvement is to return basically a string object to jquery that then updates the html control.
ddlExtBoards.append($('<option></option>').val(option.id).html(option.name + " " + option.isSelected));
So advice / direction on what approach to accomplish this "match" would be very much appreciated.

The purpose is that I want to flag the forums the user has subscribed to with "selected"
A left-join is what you want here, this means that all the records in ExtForum are included at least once and any other ones that match the join
var results = (from exf in ExtForum
join custfrm in customer.ExternalForums on
exf.Id equals custfrm.Id into customerForums
from custForum in customerForums.DefaultIfEmpty()
select new
{
id = exf.Id,
name = exf.ForumName,
isSelected = custForum != null
}

Related

Selenium - Cannot select drop-down

Picked up on a small learning project, to find the cheapest car rental by modifying dates.
Website: Costco Travel
Flow: Select Province -> Rental Cars -> Enter Airport code, change date, times.
Issue: Cannot select Pick-up Time or Drop-off Time.
My code so far (works well) -
var rootDir = Directory.GetParent(Environment.CurrentDirectory);
var chromeDriverDir = rootDir.EnumerateDirectories("ChromeDriver", SearchOption.AllDirectories);
if ((chromeDriverDir != null) && (chromeDriverDir.Count() == 0))
Environment.Exit(-1);
var Driver = new ChromeDriver(chromeDriverDir.ToList()[0].FullName);
Driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(5);
Driver.Manage().Window.Position = new System.Drawing.Point(0, 0);
Driver.Manage().Window.Maximize();
Driver.Navigate().GoToUrl("https://www.costcotravel.ca/");
Driver.FindElementByXPath("//label[contains(text(), \"Ontario\")]").Click(); // Select Province
Driver.FindElementByXPath("//button[contains(text(), \"Continue\")]").Click(); // Click on Continue
Driver.FindElementByXPath("//li[#data-tab=\"rental-cars\"]/a").Click(); // Click on "Rental Cars" Driver.FindElementById("pickupLocationTextWidget").SendKeys("yyz");
Driver.FindElementByXPath("//li[#class=\"airport\" and #data-value=\"YYZ\"]").Click(); // Select the airport
Driver.FindElementById("pickupDateWidget").Clear(); Driver.FindElementById("pickupDateWidget").SendKeys("01/05/2018"); // Select pick-up date
Driver.FindElementByXPath("//div[#id=\"pickup_time_widget\"]/input").Click();
Now, the issue -
Approach 1
new SelectElement(Driver.FindElementById("pickupTimeWidget")).SelectByText("11:00 AM");
'element not visible: Element is not currently visible and may not be
manipulated
Approach 2
Driver.FindElementByXPath("//div[#id=\"pickup_time_widget\"]/div/ul/li[#data-value=\"07:30 AM\"]").Click();
element not visible
Approach 3 - knew it wouldn't work, but tried it anyway.
new SelectElement(Driver.FindElementByXPath("//div[#id=\"pickup_time_widget\"]/div/ul/li[#data-value=\"07:30 AM\"]")).SelectByIndex(5);
Element should have been select but was li
Any help on selecting a value from pickuptime/dropofftime drop-downs is greatly appreciated! Usually, I have seen many websites implementing just the select tag, but this website also has ul/li tags, which is making it complicated. Or maybe I am over thinking. Please help!
There are underlying select elements that power these dropdowns. But, they are invisible and changed whenever the values in the "ul->li" dropdowns change.
There are two general options here:
make the select elements visible and use the SelectElement class to control the dropdowns
let the select elements be invisible and instead control the "ul->li" dropdown
The first option would just require setting the style of the select elements to "display: block":
IWebElement element = Driver.FindElementById("pickupTimeWidget");
((IJavaScriptExecutor)Driver).ExecuteScript("arguments[0].style = 'display:block';", element);
new SelectElement(element).SelectByText("11:00 AM");
The second option would first require a click to open up a dropdown:
IWebElement dropdown = Driver.FindElementById("pickup_time_widget");
dropdown.Click();
Then, finding a dropdown item by value/text and clicking it:
IWebElement dropdownItem = dropdown.FindElementByXpath(".//li[. = '11:00 AM']");
dropdownItem.Click();

Filtering Children in Entity Framework Query

I have a database which it's schema is as follows:
As you can see, We have WareCategories which will be category of the wares i'm going to be working in my website. WareTypes which will be Definition of each Item type. Categories define properties in the table WarePropertyDefinitions and WareProperties define values for each property that has been defined in WarePropertyDefinitions table.
Now i have a search page that users search for items in OldWares and user selects category and i show the user all properties defined in WarePropertyDefinitions and user fills the data if he likes better results. But my problem is that i can't filter WareTypes based on WareProperties because it's from the type ICollection and i can't access filter options.
How can i apply this kind of filtering based on properties?
Thanks in advance...
Edit:
This is a part of the code i'm presenting to describe more:
var lst = WareCategory.GetItem(Convert.ToInt32(ddlChildren.SelectedValue)).WarePropertyDefinitions.ToList();
foreach (var ListItem in lst)
{
var value = BaseHelper.FindFormValue("PropertyValue" + ListItem.Id.ToString());
if (!string.IsNullOrEmpty(value))
{
query = query.Where(m => m.WareType.WareProperties.);
}
}
}
This segment of code is in my search function and as you can see i'm going to generate a list of items in WarePropertyDefinition that user selected via a drop down menu called ddlChildren. I'm going to iterate in this definition and user entered value for each property (the value variable will hold the value user entered and i will check if user have entered anything in the textbox) i will include it in where section (through this i will add it in where clause that ultimately filters my selection). but as you can see the code is incomplete because i don't know how to complete it.
Use the Any() extension method, for example:
query = query.Where(m => m.WareType.WareProperties.Any(wp => wp.Id == 5));
I have fixed the my problem by this code:
query = query.Where(m => m.WareType.WareProperties.Any(wp => wp.WarePropertyDefinition_Id == ListItem.Id && wp.TextValue == value));
but because #user3159792's answer was the basic of my problem i have selected his answer as the default answer to my problem. very thanks.

How to find a nested selenium WebElement in C# with LINQ?

I've been learning about LINQ and am trying to apply it to finding certain web elements on the page with selenium.
I have an angular site which displays a table made up of divs. All the rows in a column, including the header, have the same attributes (e.g. css selector/classname etc).
I want to find all the input boxes within a column that are visible, and came up with this...
var applyBoxes2 = from box in driver.FindElements(By.CssSelector("div.col-apply.col-md-1"))
where box.Text != "Apply?"
select box;
var clickableBox = from box in applyBoxes2
where box.FindElement(By.TagName("input")).Displayed == true
select box.FindElement(By.TagName("input"));
The first query is required as the first row is the header, and doesn't contain an input field. If I don't have this query my second query will fall over when trying to do the findelement = "input".
Does anybody know if I can combine these 2 statements? So first I would filter out the header, then I would find each input box within each div.
Any thoughts on how else this could be improved on would be welcomed.
Many thanks,
Use the && operator, it short circuits when it doesn't pass the 1st statement. So in your case it won't try to find an element if the text is Apply?.
var clickableBox = from box in driver.FindElements(By.CssSelector("div.col-apply.col-md-1"))
where box.Text != "Apply?" && box.FindElement(By.TagName("input")).Displayed == true
select box.FindElement(By.TagName("input"));
You can do something like this
var clickableBox = driver.FindElements(By.CssSelector("div.col-apply.col-md-1"))
.Where(box => box.Text != "Apply?")
.Select(box => box.FindElement(By.TagName("input")))
.Where(boxElement => boxElement.Displayed);
You can use let clause,
to perform inner clause.
Code will be like this:
var applyBoxes2 = from box in driver.FindElements(By.CssSelector("div.col-apply.col-md-1"))
let clickableBox = box.FindElement(By.TagName("input"))
where box.Text != "Apply?" && clickableBox?.Displayed = True
select clickableBox;

distinct value from a column in a grid using linq

I am using the below query to find the the distinct value count from a dataset column. How to find similarly to a grid column.
var distinctRows = (from DataRow dRow in _ds.Tables[0].Rows
select dRow["colName"]).Distinct();
Ok..I'm still not sure why you want to do it without requerying the DataSource, but here's one way that might point you in the right direction. gv1 is the ID of your GridView, and for demonstration purposes I'll use the first column:
string[] rowValues = new string[gv1.Rows.Count];
for (int i = 0; i < gv1.Rows.Count; i++)
{
rowValues[i] = gv1.Rows[i].Cells[0].Text;
}
var distinctRows = (from r in rowValues
select r).Distinct();
This of course assumes that it's one cell per column, which may be a false (or at least bad) assumption.
UPDATE
Just saw this Can't seem to use Linq with ASP.Net Navigation menu answered by Jon Skeet, and think it might apply to the issue here.
var distinctRows = (from GridViewRow r in gv1.Rows
select r.Cells[0].Text).Distinct();
Courtesy of Jon's answer, to use LINQ in this case you need to Cast to IEnumerable (as I'm willing to bet the GridViewRowsCollection doesn't implement IEnumerable) by explicitly specifying the item, as above.
Your grid is probably bound to a data source in which case it makes more sense to use the linq query against the data source rather than the grid itself

wp7 - App.ViewModel collection Selection

I have a collection:
App.ViewModel.historyItemCollection
That has 4 properties:
id
name
meterValue
meterDate
I would like to bind to my listbox by id. So if I select house #2 (in the collection) I only want to show the history information for house 2.
I tried a couple of different selects/where statements when trying to bind it to my form:
lbHistory.ItemsSource = App.ViewModel.historyItemCollection.Where(history => history.id= houseIndex);
If there are any links that say how to do this, please just point me there? Part of my problem I couldn't figure out what this was called so my searches were fruitless.
Thanks!
I haven't tested this code, so forgive me if it doesn't work.
lbHistory.ItemsSource = from item in App.ViewModel.historyItemCollection
where item.id == houseIndex
select item;
If there can be more than one match, and you only want to show the first, use:
lbHistory.ItemsSource = ( from item in App.ViewModel.historyItemCollection
where item.id == houseIndex
select item ).FirstOrDefault();

Categories

Resources