Observable collection Raise property changed - observablecollection

private ObservableCollection<Scores> _scores;
public ObservableCollection<Scores> Scores
{
get
{
return _scores;
}
set
{
_scores = value;
RaisePropertyChanged("Scores");
Recalculate();
}
}
public int RowNumber { get; set; }
public string StudentId { get; set; }
public string StudentName { get; set; }
private double _studentAverage;
public double StudentAverage
{
get
{
return _studentAverage;
}
set
{
_studentAverage = value;
RaisePropertyChanged("StudentAverage");
}
}
private string _gradeYear;
public string GradeYear
{
get
{
return _gradeYear;
}
set
{
_gradeYear = value;
RaisePropertyChanged("StudentGrade");
}
}
private void Recalculate()
{
StudentAverage = (from score in Scores select score.Score).Sum();
}
Hi, how can i get the notification when a score changes inside ObservableCollection so that i can recalculate.
Actually i am binding the whole Entity to a Gridview. Whenever a Score changes in the column i want my Total column to automatically calculate the Total and display.

Note 1
In a nutshell - you should subscribe to INotifyPropertyChanged.PropertyChanged event of all your "scores", and in the event handler you should recalc your TotalScore. But the problem is that you should also monitor changes in your Scores collection (if you need it, of course).
As a very useful helper you can try to use my Extended ObservableCollection. This class already contains ItemPropertyChangedEvent, so you should just write something like:
private ObservableCollectionEx<Scores> _scores;
public ObservableCollectionEx<Scores> Scores
{
get
{
return _scores;
}
set
{
if (_scores == value) return;
if (_scores != null)
_scores.ItemPropertyChanged -= OnItemPropertyChanged;
_scores = value;
if (_scores != null)
_scores.ItemPropertyChanged += OnItemPropertyChanged;
RaisePropertyChanged("Scores");
Recalculate();
}
}
void OnItemPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "Score")
Recalculate();
}
Note 2
Take a look also at this article. It will teach how to avoid "magic strings" in notifications (like RaisePropertyChanged("Scores") and e.PropertyName == "Score").
Note 3
Instead of
StudentAverage = (from score in Scores select score.Score).Sum();
it's better to use
StudentAverage = Scores.Sum(score => score.Score);
But this is not necessarily, this is just my style of coding :)
BTW, why it's mixed - "average" and "sum"? Is this mistake?

Related

asp.net core delete everything with certain number

I want to delete all vragen(questions in english) with the classID for example number 5. It is possible to give a vraagID and a classID and the server deletes the question if it matches. But I want to delete all matching questions with only one request. Is this possible?
namespace AspIdentityServer.data
{
public class Vraag :Conversatie
{
public int VraagID { get; set; }
public int classID { get; set; }
public string Titel { get; set; }
public ICollection<Antwoord> Antwoord { get; set; }
public Vak Vak { get; set; }
}
}
--
// DELETE: api/Vraags/1/alles/5
[AllowAnonymous]
[HttpDelete("{id}/alles/{vakID}")]
public async Task<IActionResult> DeleteAlleVragen([FromRoute] int id, int vakID) {
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var vraag = await _context.Vraag.SingleOrDefaultAsync(m => m.VraagID == id);
if (vraag.classID == vakID)
{
_context.Vraag.Remove(vraag);
await _context.SaveChangesAsync();
}
return Ok(vraag);
}
You can always use the ExecuteSqlCommandAsync to execute your custom SQL queries. So write a single delete statements with appropriate where clause which will handle many rows as needed.
Here is a quick example
object[] paramsArray =
{
new SqlParameter
{
ParameterName = "#vraagId",
SqlDbType = SqlDbType.Int,
Value = id
},
new SqlParameter
{
ParameterName = "#classId",
SqlDbType = SqlDbType.Int,
Value = vakID
}
};
const string q = "DELETE FROM VraagWHERE VraagID=#vraagId and ClassId=#classId";
await _context.Database.ExecuteSqlCommandAsync(q, paramsArray);
Update the SQL statemenets and parameters as needed.

Orchard 1.10.2 TryUpdateModel not working after upgrade from 1.7

Newbie to Orchard CMS
After upgrading an existing Orchard site running version 1.7 to version 1.10.2, some (not all) of my content part drivers are no longer updating the part properties with the new values entered into the form on add or edit.
When I go into add or edit an item, the only property that is saved is an MediaPickerField that is a field of the part.
I have compared the non-working code with working content part drivers in the solution and I can't see anything that is different from them that would cause the issue.
TryUpdateModel is returning true, but none of the values on the form flow through. On Add, there will be a record in the DB with all empty fields except the Id. The driver returns the edit view with a message that the part was added successfully, but all the fields are cleared out except the Image field.
Here is the code for one of the parts having the issue.
public class FeaturedPromoPartRecord : ContentPartRecord {
[StringLength(100)]
public virtual string Name { get; set; }
[StringLengthMax]
public virtual string LinkUrl { get; set; }
public virtual FeaturedPromoGroupPartRecord FeaturedPromoGroupPartRecord { get; set; }
public virtual int SlideOrder { get; set; }
public virtual DateTime? StartDate { get; set; }
public virtual DateTime? EndDate { get; set; }
}
public class FeaturedPromoPart : ContentPart<FeaturedPromoPartRecord> {
public string Name
{
get { return Record.Name; }
set { Record.Name = value; }
}
public string LinkUrl {
get { return Record.LinkUrl; }
set { Record.LinkUrl = value; }
}
public FeaturedPromoGroupPartRecord FeaturedPromoGroupPartRecord
{
get { return Record.FeaturedPromoGroupPartRecord; }
set { Record.FeaturedPromoGroupPartRecord = value; }
}
public int SlideOrder {
get { return Record.SlideOrder; }
set { Record.SlideOrder = value; }
}
public DateTime? StartDate
{
get { return Record.StartDate; }
set { Record.StartDate = value; }
}
public DateTime? EndDate
{
get { return Record.EndDate; }
set { Record.EndDate = value; }
}
}
public class FeaturedPromoPartDriver : ContentPartDriver<FeaturedPromoPart> {
private readonly IFeaturedPromoService _featuredPromoService;
public FeaturedPromoPartDriver(IFeaturedPromoService featuredPromoService) {
_featuredPromoService = featuredPromoService;
T = NullLocalizer.Instance;
}
public Localizer T { get; set; }
protected override DriverResult Display(FeaturedPromoPart part, string displayType, dynamic shapeHelper) {
var group = _featuredPromoService.GetFeaturedPromoGroup(part.FeaturedPromoGroupPartRecord.Id);
return ContentShape("Parts_FeaturedPromo_SummaryAdmin",
() => shapeHelper.Parts_FeaturedPromo_SummaryAdmin(ContentPart: part, ContentItem: part.ContentItem, Group: group));
}
protected override DriverResult Editor(FeaturedPromoPart part, dynamic shapeHelper) {
var groups = _featuredPromoService.GetFeaturedPromoGroups();
var viewModel = new FeaturedPromoEditViewModel
{
Groups = groups,
Name = part.Name,
FeaturedPromoGroupPartRecordId = (part.FeaturedPromoGroupPartRecord == null) ? 0 : part.FeaturedPromoGroupPartRecord.Id,
LinkUrl = part.LinkUrl,
SlideOrder = part.SlideOrder,
StartDate = part.StartDate,
EndDate = part.EndDate
};
return ContentShape("Parts_FeaturedPromo_Edit",
() => shapeHelper.EditorTemplate(TemplateName: "Parts.FeaturedPromo.Edit", Model: viewModel));
}
protected override DriverResult Editor(FeaturedPromoPart part, IUpdateModel updater, dynamic shapeHelper) {
var result = updater.TryUpdateModel(part, Prefix, null, null);
var group = _featuredPromoService.GetFeaturedPromoGroup(part.FeaturedPromoGroupPartRecord.Id);
if(group != null)
part.FeaturedPromoGroupPartRecord = group._record.Value;
if (part.StartDate.HasValue && part.EndDate.HasValue && part.StartDate > part.EndDate)
updater.AddModelError("", T("The End Date cannot be after the Start Date."));
return Editor(part, shapeHelper);
}
}
Some images of what I'm seeing.
Edit
Add New
If anyone has encountered this issue, or has some insight on how to fix I would greatly appreciate your help!
Thank you

In Orchard how do I create a query that includes an associated Part?

I'm working in a new module for an orchard project. We've build a Company Part which is associated with an Address Part. What I'm eventually trying to get to is allowing users to enter various search criteria via the ui (non-admin interface), perform a search against all companies and return any matching results.
Where I'm struggling is how to build the query which allows me to include info from the associated address. So far I've only been able to successfully return results based on the CompanyPartRecord as opposed to the CompanyPart. The CompanyPartRecord obviously only contains the Address_Id of the associated AddressPart.
In essence I'm trying to get to something like this which will return an enumerable or list of companies which match the entered search criteria. There are more search options beyond zip so I'm looking for an extensible solution.
var query = _companyRepository.Table.AsQueryable();
if (!string.IsNullOrEmpty(Zip))
query = query.Where(c => c.Address.Zip == Zip);
var queryResult = query.ToList();
I've tried using both an IRepository (shown above) and with IContentManager such as the following:
var query = _contentManager.Query<CompanyPart, CompanyPartRecord>();
//var query = _contentManager.Query<CompanyPart>();
if (!string.IsNullOrEmpty(Zip))
query = query.Where(c => c.Address.Zip == Zip);
var queryResult = query.ToList();
Here's the actual Company and Address (Parts and Records):
public class CompanyPartRecord : ContentPartRecord
{
public virtual string Name { get; set; }
public virtual string Description { get; set; }
public virtual int Address_Id { get; set; }
public virtual string Phone { get; set; }
public virtual string OtherInformation { get; set; }
public virtual string Website { get; set; }
public virtual bool Inactive { get; set; }
// Keywords - Taxonomy
// Logo - associated part
// HasMissingData - derived
// NumberOfEmployees - associated part
}
public class CompanyPart : ContentPart<CompanyPartRecord>, ITitleAspect
{
internal readonly LazyField<AddressPart> AddressField = new LazyField<AddressPart>();
public string Name
{
get { return Record.Name; }
set { Record.Name = value; }
}
public string Description
{
get { return Record.Description; }
set { Record.Description = value; }
}
public AddressPart Address
{
get { return AddressField.Value; }
set { AddressField.Value = value; }
}
public string Phone
{
get { return Record.Phone; }
set { Record.Phone = value; }
}
public string OtherInformation
{
get { return Record.OtherInformation; }
set { Record.OtherInformation = value; }
}
public string Website
{
get { return Record.Website; }
set { Record.Website = value; }
}
public bool Inactive
{
get { return Record.Inactive; }
set { Record.Inactive = value; }
}
public string Title
{
get { return Name; }
}
}
public class AddressPartRecord : ContentPartRecord
{
public virtual string Street { get; set; }
public virtual string Street2 { get; set; }
public virtual string City { get; set; }
public virtual string CountyName { get; set; }
public virtual NationRecord State { get; set; }
public virtual string Zip { get; set; }
}
public class AddressPart : ContentPart<AddressPartRecord>
{
public string Street
{
get { return Record.Street; }
set { Record.Street = value; }
}
public string Street2
{
get { return Record.Street2; }
set { Record.Street2 = value; }
}
public string City
{
get { return Record.City; }
set { Record.City = value; }
}
public string CountyName
{
get { return Record.CountyName; }
set { Record.CountyName = value; }
}
public NationRecord State
{
get { return Record.State; }
set { Record.State = value; }
}
public string Zip
{
get { return Record.Zip; }
set { Record.Zip = value; }
}
}
I assume that you have a Content Type that contains both Parts (ie. named Company), if that is the case this should work:
var query = _contentManager.Query("Company").Where<AddressPartRecord>(x => x.Street == "query street");
var list = query.ToList();
The list contains the ContentItems filtered by street. Using .As() and .As() over the items of the list you get access to each part.

Accessing XPages Data Source in a Plugin

For a plugin (like the extension library) I try to access the datasource with a given "var" name. Accessing the Datasource object is very easy with the following code:
m_DataSourceName contains the name (var) of the datasource.
public DataSource getDataSource() {
if (StringUtil.isNotEmpty(m_DataSourceName)) {
UIViewRoot vrCurrent = getFacesContext().getViewRoot();
if (vrCurrent instanceof UIViewRootEx) {
for (DataSource dsCurrent : ((UIViewRootEx) vrCurrent)
.getData()) {
if (m_DataSourceName.equals(dsCurrent.getVar())) {
return dsCurrent;
}
}
}
}
System.out.println("Datasource name:" + m_DataSourceName);
return null;
}
I'm getting the datasource back and I can cast this datasource:
private TabularDataModel getTDM(DataSource dsCurrent, FacesContext context) {
try {
if (dsCurrent instanceof ModelDataSource) {
ModelDataSource mds = (ModelDataSource) dsCurrent;
AbstractDataSource ads = (AbstractDataSource) mds;
ads.load(context);
System.out.println(ads.getBeanId());
if (ads.getBeanId() == null) {
}
DataModel tdm = mds.getDataModel();
if (tdm instanceof TabularDataModel) {
TabularDataModel tds = (TabularDataModel) tdm;
return tds;
}
}
return null;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
And now I wanna access the TDM.getRowCount() and this point I'm getting a nullpointer exception. The datasource contains a notes view. Did I miss anything to initialize the datasource?
Here is a solution for your problem:
This will give you all lines of a view, not the entry count*. F.e. if you have a categorized view with 5 categories and 1 entry for each category, this will result in 10 lines. The entry count is 5.
First, create a dummy class which implements FacesDataIterator
public class DummyDataIterator implements com.ibm.xsp.component.FacesDataIterator{
public DataModel getDataModel() {
return null;
}
public int getFirst() {
return 0;
}
public int getRowIndex() {
return 0;
}
public int getRows() {
return 0;
}
public void setFirst(int paramInt) {}
public void setRows(int paramInt) {}
}
And then you have to do the following:
Set the data iterator
tdm.setDataControl( new DummyDataIterator() );
Init the row counter for the first time
tdm.getRowCount();
Calculate the exact row count with a navigator
(( com.ibm.xsp.model.domino.viewnavigator.NOIViewNavigatorEx) tdm.getDominoViewDataContainer().getNavigator()).calculateExactCount(tdm.getView());
Now your row count is initialized, you can get the result with a normal getRowCount:
System.out.println("Rows: " + tdm.getRowCount() );
Hope this helps!
*:
tdm.getView().getAllEntries().getCount()

Array List in C# without a loop

I like to know how to initialise the array without the loops like for, foreach or any LINQ.
From the following code, need to find under 2m length cars within .Netframework using console application.
{
ArrayList = CarType new ArrayList();
CarType.Add(new CarList("Ford"));
((CarList)CarType[0]).Cars.Add(new Car("Focus", 2));
((CarList)CarType[0]).Cars.Add(new Car("Fiesta", 1));
CarType.Add(new CarList("Peugeout"));
((CarList)CarType[1]).Cars.Add(new Car("206", 1));
((CarList)CarType[1]).Cars.Add(new Car("407", 2));
RemoveLargeCars(CarType);
}
public static ArrayList RemoveLargeCars (ArrayList CarType)
{
//Array List should be here
return CarType;
}
It has got two classes as follows.
class Car
{
public string name;
public float length;
public Car(string newName, float newLength)
{
this.name = newName;
this.length = newLength;
}
}
Class CarList
{
public string CarType;
public ArrayList Pipes;
public CarList(string newCarType)
{
carType = newCarType;
Cars = new ArrayList();
}
}
Can you please let me know how to solve this.
Thanks in advance.
Use the static Adapter method on ArrayList
CarType = ArrayList.Adapter(CarList);
But that probably uses a loop internally, you can't get away from them, but at least this hides them.
Well, first of all you should use the generic list type List<T> instead of ArrayList, that will make the code simpler. (And best practive recommends properties rather than public fields):
class Car {
public string Name { get; set; }
public float Length { get; set; }
public Car(string newName, float newLength) {
Name = newName;
Length = newLength;
}
}
class CarList {
public string CarType { get; set; }
public List<Car> Cars { get; set; }
public CarList(string newCarType, List<Car> newCars) {
CarType = newCarType;
Cars = newCars;
}
public CarList(string newCarType) : this(newCarType, new List<Car>()) {}
}
Now use a List<CarList>:
List<CarList> CarType = new List<CarList>();
CarList ford = new CarList("Ford");
CarType.Add(ford);
ford.Cars.Add(new Car("Focus", 2));
ford.Cars.Add(new Car("Fiesta", 1));
CarList peugeot = new CarList("Peugeout");
CarType.Add(peugeot);
peugeot.Cars.Add(new Car("206", 1));
peugeot.Cars.Add(new Car("407", 2));
List<CarList> smallCars = RemoveLargeCars(CarType);
You can use extension methods to easily filter out cars based on a condition:
public static List<CarList> RemoveLargeCars(List<CarList> CarType) {
return CarType.Select(
t => new CarList(t.CarType, t.Cars.Where(c => c.Length < 2f).ToList()
) .ToList();
}
Note that the method doesn't change the original list, but creates a new list.

Resources