简体   繁体   中英

ObservableCollection on derived class

I'm a beginner developer in C# (coming from a SQL background) so some of the terminology in this question may be incorrect..apologies in advance.

I'm trying to create a Food Consumption Tracking application (allows you to track what meals you ate, count calories etc.) using C#/WPF/SQLite. I've created the Database piece, and the Entity model using the Add-Model wizard in EF.

I have a ConsumptionLog entity, like so

public partial class ConsumptionLog
{
    public int consumptionID { get; set; }
    public Nullable<int> dayMealNumber { get; set; }
    public Nullable<int> foodID { get; set; }
    public Nullable<int> mealID { get; set; }
    public Nullable<decimal> servings { get; set; }
    public System.DateTime logDate { get; set; }

    public virtual Meal Meal { get; set; }
    public virtual Food Food { get; set; }


}

and

public partial class Food
{
    public Food()
    {
        this.ConsumptionLogs = new HashSet<ConsumptionLog>();
        this.MealContents = new HashSet<MealContent>();
    }

    public int foodID { get; set; }
    public string store { get; set; }
    public string brandName { get; set; }
    public string foodName { get; set; }
    public string foodUnit { get; set; }
    public Nullable<decimal> foodNoOfUnits { get; set; }
    public Nullable<decimal> calories { get; set; }
    public Nullable<decimal> carb { get; set; }
    public Nullable<decimal> sugar { get; set; }
    public Nullable<decimal> protein { get; set; }
    public Nullable<decimal> fat { get; set; }
    public Nullable<decimal> fibre { get; set; }
    public Nullable<decimal> gms { get; set; }
    public Nullable<decimal> ml { get; set; }
    public short isActive { get; set; }
    public virtual ICollection<MealContent> MealContents { get; set; }
}

The above code was auto-generated. What I'm trying to do is extend the ComsumptionLog in another class, to add more properties. For example, this is a snippet...

    public partial class ConsumptionLogView : ConsumptionLog
{
    public ObservableCollection<ConsumptionLogView> CLViewList { get; set; }

    string _FoodName;
    public string FoodName
    {
        get
        {
            if (Food == null)
            {
                return "Total";
            }
            else
            {
                return Food.foodName.ToString() + " : " 
                    + Convert.ToDouble(Food.foodNoOfUnits).ToString() + " " + Food.foodUnit.ToString();
            }
        }
        set
        {

        }
    }

    public decimal _Calories;
    public decimal Calories
    {
        get
        {
            if (Food == null)
            {
                return _Calories;
            }
            else
            {
                return Convert.ToDecimal(Food.calories);
            }
        }
        set
        {

        }
    }
}

With the aim that, I can use something like this

private void LoadConsumptionLogs()
    {
        FitnessLogDBEntities ctx = new FitnessLogDBEntities();
        var consumptionList = (
                                    from s in ctx.ConsumptionLogs
                                    where s.logDate == LogDate.SelectedDate.Value
                                    select s).ToList<ConsumptionLog>();

        ObservableCollection<ConsumptionLogView> conLogViewColl = 
            (ObservableCollection<ConsumptionLogView>)consumptionList.Cast<ObservableCollection<ConsumptionLogView>>();

        var consumptionItem = new ConsumptionLogView();
        consumptionItem._Calories = GetTotalCals(conLogViewColl);
        conLogViewColl.Add(consumptionItem);
        ConsumptionLog.ItemsSource = conLogViewColl;
    }

private decimal GetTotalCals(ObservableCollection<ConsumptionLogView> cons)
    {
        double Total = 0;
        foreach (ConsumptionLogView con in cons)
        {
            Total += Convert.ToDouble(con.Calories);
        }
        return Convert.ToDecimal(Total);
    }

Clearly, this is not working and is tripping up at the point where I am trying to cast the base class ObservableCollection (ConsumptionLog) to the derived class (ConsumptionLogView)

My questions were:

  1. The code was working when I only had the base class and amended that with the Total calories portion of the code. Only that, if at that point, if I amended the Database structure slightly, and refreshed in VS, the class and code got overwritten. So I started to go down this road of separating the additional code. Am I incorrect in trying to do something like this (separating code in classes)?
  2. If not, am I close in trying to populating the base class obs. coll. and going about "copying" the collection contents into the derived class obs. collection? I thought since ConsumptionLogView has all of Consumption + some, that I would be able to cast it.

I searched on SO and other places but wasn't sure exactly what to search for, so any assistance would be appreciated. If there are pointers to other working examples, that would also be some place I can start.

Thanks in advance, S

You don't need necessarily to use inheritance to extend a class. A second way to extend a class in C# is using partial classes. This means a class consists out of multiple files. Typically autogenerated classes are already partial. This means extending the class is quite simple. Let's say the code generator created the ComsumptionLog.cs (note the partial identifier)

public partial class ConsumptionLog
{
    //Some properties
}

You only need to create a second file like ComsumptionLogExtension.cs

public partial class ConsumptionLog
{
    //Additional properties and methods
}

with all the additional properties and methods you need. For more information have a look at Microsofts description of partial classes . This way you don't need to cast any type since the class is still the same. If you save the extension file in a different folder than your generated files the code generator should not touch it during generation runs. Note that the namespace have to be the same.

I think this approach should solve your problems in a very clean and simple way.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM