Is there an easy way to reverse the default order of a drop down list?
if (_group.Category == GroupCategory.Workers ||
_group.Category == GroupCategory.Acct)
{
this.cboList.DataSource = null;
this.cboList.DisplayMember = "DescForMCE";
this.cboList.ValueMember = "ID";
this.cboList.DataSource = _ch.Accounts;
this.cboList.Visible = true;
this.lblList.Visible = true;
}
You can reverse the order of the data source before you bind it.
if (_group.Category == GroupCategory.Workers ||
_group.Category == GroupCategory.Acct)
{
this.cboList.DataSource = null;
this.cboList.DisplayMember = "DescForMCE";
this.cboList.ValueMember = "ID";
this.cboList.DataSource = _ch.Accounts.Reverse();
this.cboList.Visible = true;
this.lblList.Visible = true;
}
Depending on the exact type and .NET version of your data source collection, it might not be quite as simple as the above example, which assumes that the data source implements IEnumerable<T> and can directly use the Reverse() extension method[MSDN].
If you only have an IEnumerable (the non-generic version) for instance, you can still accomplish in two calls using Cast<T>()[MSDN]:
collection.Cast<YourType>().Reverse();
Or your collection class might have its own implementation of Reverse(), like List<T>[MSDN] or Array[MSDN]
As other friends have suggested, it is better to fetch your data in a descending order and after that simply bind it to any control you may wish. Here is a stored procedure plus a LINQ query which bring data as you need:
The Linq query:
var queru = new DatabaseContext().Cities.OrderByDescending(s => s.CityID).ToList();
and the SP:
SELECT * FROM Roles
ORDER BY RoleID DESC
Hope it helps,
You can have the data you use for your datasource be in reverse before putting it in your dropdown list.
Use .Reverse.
Related
I have Ilist to get all Offer from repository using entity framework core. Also I have service model OfferResponseModel which includes
OfferRequestModel as reference. I used mapster to bind entity model to service model. However it only set first child. Now I want to bind it manually. I created "offers" with the size of "Offer". When I try to use foreach loop, I cannot set "offers" child element.Because it has no elements. So, I can I solve this.
var offer = await _unitOfWork.Offers.GetAllOffer();
if (offer == null)
throw ServiceExceptions.OfferNotFound;
var results = new List<OfferResponseModel>(offer.Count);
results.ForEach(c => { c.Offer = new OfferRequestModel(); });
int i = 0;
foreach(var result in results)
{
result.Offer.User = Offer[i].User.Adapt<UserResponseModel>();
result.Offer.Responsible = Offer[i].Responsible.Adapt<EmployeeResponseModel>();
result.CreatedDate = Offer[i].CreatedDate;
result.ModifiedBy = Guid.Parse(Offer[i].UpdatedBy);
result.Active = Offer[i].Status;
result.Offer = Offer[i].Offer;
result.Offer.User.Company = Offer[i].Company.Adapt<CompanyModel>();
i++;
}
I created "offers" with the size of "Offer".
No, you created it with that capacity. It's still an empty list. It's not clear to me why you're trying to take this approach at all - it looks like you want one OfferResponseModel for each entry in offer, directly from that - which you can do with a single LINQ query. (I'm assuming that offer and Offer are equivalent here.)
var results = Offer.Select(o => new OfferResponseModel
{
Offer = new OfferRequestModel
{
User = o.User.Adapt<UserResponseModel>(),
Responsible = o.Responsible.Adapt<EmployeeResponseModel>()
},
CreatedDate = o.CreatedDate,
ModifiedBy = Guid.Parse(o.UpdatedBy),
Active = o.Status
}).ToList();
That doesn't set the Offer.User.Company in each entry, but your original code is odd as it sets the User and Responsible properties in the original Offer property, and then replaces the Offer with Offer[i].Offer. (Aside from anything else, I'd suggest trying to use the term "offer" less frequently - just changing the plural to "offers" would help.)
I suspect that with the approach I've outlined above, you'll be able to work out what you want and express it more clearly anyway. You definitely don't need to take the "multiple loops" approach of your original code.
One thing you have left out is the type of the offer variable that is referenced in the code. But I am thinking you need to do something along these lines:
if (offer == null)
throw ServiceExceptions.OfferNotFound;
var results = offer.Select(o => new OfferResponseModel
{
Offer = new OfferRequestModel
{
User = o.User.Adapt<UserResponseModel>(),
Responsible = o.Responsible.Adapt<EmployeeResponseModel>(),
...
}
}).ToList();
Select basically loops through any items in offer and "converts" them to other objects, in this case OfferResponseModel. So inside select you simply new up an OfferResponseModel and directly sets all the properties you need to set.
You need using System.Linq; for Select to be available.
I am new to LINQ and I have a question regarding a "Hit the database once" type of transaction.
In the below code I am databinding the results of a query to a radio list. I want to run the query once, then work with the results before databinding. IE: If there are values, databind to the Radio list, otherwise show a textbox stating there are no values.
From my online searches I have only found that I can run the query once with a .count(), then run it again if the .count() is > 0.
I would prefer to hit the database once, then count the records, and proceed using the same resultset.
I was not sure of the terminology to use when searching, so please respond with the approprate terminology to use so that I can find the answer on my own!
using (RTOExceptionDataContext thisDataContext = new RTOExceptionDataContext())
{
rdoSelectTransition.DataSource = from tracking in thisDataContext.vw_RTOExceptionWorkflowTransitionMaps
where tracking.RTOExceptionId.Equals(Convert.ToInt32(Request.QueryString["RTOExceptionId"])) &&
tracking.RTOSecurityLevel.Equals((int)Master.thisUserSecurityLevel)
select new { tracking.RTOTransitionCd, tracking.TransitionDisp };
rdoSelectTransition.DataTextField = "TransitionDisp";
rdoSelectTransition.DataValueField = "RTOTransitionCd";
rdoSelectTransition.DataBind();
}
You don't need to do this at all. Just keep your binding code exactly as it is and use the <EmptyDataTemplate> within the markup of the GridView to indicate what should be shown in the event that you bind an empty collection to the GridView.
If you're binding data to a type of control that doesn't support a feature like this, then the easiest option is to simply eagerly materialize the query into a collection and then get the size of that in-memory collection.
var data = (from tracking in thisDataContext.vw_RTOExceptionWorkflowTransitionMaps
where tracking.RTOExceptionId.Equals(Convert.ToInt32(Request.QueryString["RTOExceptionId"])) &&
tracking.RTOSecurityLevel.Equals((int)Master.thisUserSecurityLevel)
select new { tracking.RTOTransitionCd, tracking.TransitionDisp })
.ToList();
if(data.Any())
//databind
else
//do something else
I did find an answer to my question! I am learning more about LINQ everyday, and I really love it! This allowed me to databind if there are results. Though the "else" is not shown below, it sets the visibility of the radio button to false.
int thisUserSecurityLevel = (int)Master.thisUserSecurityLevel;
int thisUserSelectedException = Convert.ToInt32(Request.QueryString["RTOExceptionId"]);
using (RTOExceptionDataContext thisDataContext = new RTOExceptionDataContext())
{
var query = from tracking in thisDataContext.vw_RTOExceptionWorkflowTransitionMaps
where tracking.RTOExceptionId.Equals(thisUserSelectedException) &&
tracking.RTOSecurityLevel.Equals(thisUserSecurityLevel)
select new { tracking.RTOTransitionCd, tracking.TransitionDisp };
if (query.Count() > 0)
{
rdoSelectTransition.DataSource = query;
rdoSelectTransition.DataTextField = "TransitionDisp";
rdoSelectTransition.DataValueField = "RTOTransitionCd";
rdoSelectTransition.DataBind();
}
}
}
How to filter a combobox based on another combobox? ... again :)
I'm writing an web app to learn. I'm using Visual Studio 2012, Silverlight 5, C#, and SQl Server for the data source.
I have one table loading into a datagrid and comboboxes to filter the datagrid. Up to this point everything is working just right.
The comboboxes are "FilterState" and "FilterWaterWay". Note they are not in the datagrid.
I want to select a state and re-populate the FilterWaterWay with only those waterways in the state.
I've seen a lot of ways to do this but none of them seem to match my setup. I could be wrong and just not know it.
From a learning standpoint, I would like to know how to implement this in all 3 of the following query data examples but I'll settle for just one. The last one is my favorite.
Thanks for any and all help.
I would not mind using the following to load comboboxes, filtered or not, but I can't firgure out how to
Restirct the GetQuery to only one field
Make that field distinct
This loads all data from the GetQuery to the datagrid.
LoadOperation<MASTER_DOCKS> loadOp = this._DocksContext.Load(this._DocksContext.GetMASTER_DOCKSQuery());
DocksGrid.ItemsSource = loadOp.Entities;
This loads all data from the GetQuery to the datagrid after it's been filtered
EntityQuery<MASTER_DOCKS> query = _DocksContext.GetMASTER_DOCKSQuery();
query = query.Where(s => s.WTWY_NAME == WaterwaytoFilterBy && s.STATE == StateToFilterBy);
LoadOperation<MASTER_DOCKS> loadOp = this._DocksContext.Load(query);
DocksGrid.ItemsSource = loadOp.Entities;
This is how I am currently loading the comboboxes. This works fine for the load but I don't see how to filter.
The DomainService.cs does not know my other combobox (FilterState) that I want to use as the filter for this combobox (FilterWaterway).
If I could query the ObservableCollection in the xaml I might be able to get it to work but it seems kind of chunky.
Adapted from http://www.jonathanwax.com/2010/10/wcf-ria-services-datagrid-filters-no-domaindatasource-2/
XAML =
private ObservableCollection<string> waterWayFilterList;
public ObservableCollection<string> WaterWayFilterList
{
get { return waterWayFilterList; }
set { waterWayFilterList = value; }
}
private void DoPopulateFilter()
{
//Call Invoke Method to get a list of distinct WaterWays
InvokeOperation<IEnumerable<string>> invokeOp = _DocksContext.FillWaterWayList();
invokeOp.Completed += (s, e) =>
{
if (invokeOp.HasError)
{
MessageBox.Show("Failed to Load Category Filter");
}
else
{
//Populate Filter DataSource
WaterWayFilterList = new ObservableCollection<string>(invokeOp.Value);
//Add a Default "[Select]" value
WaterWayFilterList.Insert(0, "[Select WaterWay]");
FilterWaterWay.ItemsSource = WaterWayFilterList;
FilterWaterWay.SelectedItem = "[Select WaterWay]";
}
};
}
DomainService.cs =
[Invoke]
public List<string> FillWaterWayList()
{
return (from r in ObjectContext.MASTER_DOCKS
select r.WTWY_NAME).Distinct().ToList();
}
Here's the closest I've gotten so far and it seems straight forward.
It returns no errors but the displayed result reads System.Collections.Generic.List'1[System.Char]
The record count in the dropdown is correct which leads me to think it's on the right track.
Only what is displayed is wrong. A casting problem perhaps?
I would still have to get the result from the FilterState Combo box in where "TX" is.
var filter = from r in _DocksContext.MASTER_DOCKS
where r.STATE.Equals("TX")
select r.WTWY_NAME.Distinct().ToList();
MyComboBox.ItemsSource = filter;
Without parentheses, you're doing the .Distinct().ToList() on the string (which implements IEnumerable<char>, which is why those operations work), which results in a List<char> (which isn't what you're looking for). You need to add parentheses so you get the distinct waterways:
var filter = (from r in _DocksContext.MASTER_DOCKS
where r.STATE.Equals("TX")
select r.WTWY_NAME).Distinct().ToList();
Note that if two waterways might have the same name, but actually be distinct, you'll need to instead select distinct r, and then differentiate them in the dropdown somehow, e.g.
var filter = (from r in _DocksContext.MASTER_DOCKS
where r.STATE.Equals("TX")
select r).Distinct().ToList();
// generated classes are partial, so you can extend them in a separate file
public partial class MASTER_DOCKS
{
// the dropdown uses the ToString method to show the object
public override string ToString()
{
return string.Format("{0} ({1})", WTWY_NAME, ID);
}
}
I have a list collection in my class library that uses a sql datareader to returns a list of family details
public class Dataops
{
public List<Details> getFamilyMembers(int id)
{
some of the database code..
List<Details> fammemdetails = new List<Details>();
Details fammember;
while (reader.Read())
{
fammemdetails = new Details((
reader.GetString(reader.GetOrdinal("PHOTO")));
fammemdetails.add(fammember);
}
return fammemdetails;
}
}
So i reference the dll to my project and would like to bind an image to one of my datareader values.
MyProject
DataOps ops = new DataOps();
myimage.ImageUrl = ??? (how do i access the list collections return image value here?
I am able to bind a datasource to the entire method like so
dropdownlistFamily.DataSource = mdb.GetFamilyMembers(id);
But cant figure out how to just grab a single value from there
You can use First/FirstOrDefault, Single/SingleOrDefault depending on your requirement. This would give you a single item from the List and you can access its ImageUrl property.
var item = mdb.GetFamilyMembers(id).FirstOrDefault();
if(item != null)
myimage.ImageUrl = item.ImageUrlProperty;
If you want to get some specific object from the list based on the condition then you can do:
var item = mdb.GetFamilyMembers(id).FirstOrDefault(r=> r.ID == someID);
You may see: LINQ Single vs SingleOrDefault vs First vs FirstOrDefault
You can use FirstOrDefault or SingleOrDefault. Or specify a predicate and use Where.
var firstValue = ops.getFamilyMembers(1).FirstOrDefault();
Use index to access particular record in the collection. You will need to ensure that element exists at the index you given in indexer, otherwise you will get exception. It is zero based index so first element will be at zero index.
var familyMembers = mdb.GetFamilyMembers(id);
if(familyMembers.Count > 0)
myimage.ImageUrl = familyMembers[0].ImageURLProperty;
I´m having a problem, I retrieve all the Loans I have stored in my database like this:
list_loans = db.Loan.Where(x => x.State.id_state != 6).ToList();
db is the Object context.
Then, I assign that list as the DataSource for my DataGridView.
dgv_Loans.Datasource = list_loans;
With that info, I add some columns. Like for example, installments left to pay. I get that value by counting the result of a query.
The user can order the result using some options. Is easy to order the result from the fields that the entity have (using linq), but I dont know how to order the results using this new columns.
I read some posts here and tried this:
dgv_Loans.Sort(dgv_Loans.Columns["installments_left"], ListSortDirection.Ascending);
By doing this, I´m getting the following exception at runtime:
"DataGridView control must be bound to an IBindingList object to be sorted."
Is there anyway to use linq to orderby created columns in a DataGridViewColumn? Or how can I solve this error?
I know there are related posts, but after reading them, I can´t find a solution to this specific problem. Thats why I showed how I implemented to get some advice..
Rather than binding directly to the list retrieved from database, what I generally do is have a view class and have all the calculated properties in that class
public class LoanView : Loan {
public LoanView(Loan loan){
}
public int InsallmentsLeft { get { return ...; } }
}
and then bind the datasource to a list of this, this keeps sorting working.
Concerning about Sort datagridview by created columns using Entity Framework
I guess you need this Presenting the SortableBindingList<T>
Usage:
loanBindingSource.DataSource = new SortableBindingList<Loan>(list_loans.ToList());
dgv_Loans.Datasource = loanBindingSource;
int ID = Convert.ToInt32(cmbDepartments.SelectedValue);
var EmployeeList = from Employee in db.Employee
where Employee.DepartmentID == ID
select new
{
Employee.FirstName,
Employee.LastName
};
dataGridView1.DataSource = EmployeeList.ToList();
You could directly give the data source to dataGridView1.DataSource but you must write ToList() at the end of your query:
int ID = Convert.ToInt32(cmbDepartmanlar.SelectedValue);
dataGridView1.DataSource = (from Employee in db.Employee
where Employee.DepartmentID == ID
select new
{
Employee.FirstName,
Employee.LastName
}).ToList();