Display two lists of models categorized by time

I have two lists of model types that are initialized in the controller and values are inserted into them. These list objects are then assigned to ViewData so that I can iterate through them using a foreach loop. However, the issue is that the models of these two lists have a 'Time' property, and I want to print these two lists ordered by their time values. Here is my code:

Model of List1:

public class Likes
{
    public string UserName { get; set; }
    public string UserPhoto { get; set; }
    public int UserId { get; set; }
    public string PostText { get; set; }
    public int? PId { get; set; }
    public DateTime? Liketime { get; set; }
}

Model of List2:

public class Comments
{
    public string UserName { get; set; }
    public string UserPhoto { get; set; }
    public int UserId { get; set; }
    public string CommentText { get; set; }
    public int? PId { get; set; }
    public DateTime? Commenttime { get; set; }
}

Controller:

public ActionResult Home()
{   
    List<Likes> List = new List<Likes>();
    var f = (from n in _db.PostLikes where n.ToWhomId == CurrentUser.User.Id join o in _db.Users on n.UserId equals o.Id join p in _db.Posts on n.PostId equals p.Id select new { Name = o.UserName, Photo = o.UserPhoto, ID = n.UserId, PID = n.PostId ,p.PostText,n.Time }).ToList().OrderByDescending(n=>n.Time);
    foreach (var item in f)
    {
        Likes mylikes = new Likes()
        {
            PId = item.PID,
            UserName = item.Name,
            UserPhoto = item.Photo,
            Posttext=item.PostText,
            Liketime=item.Time
        };
        List.Add(mylikes);
    }
    ViewData["likes"] = List;
    
    List<Comments> List2 = new List<Comments>();
    var qw = (from n in _db.PostComments where n.ToWhomId == CurrentUser.User.Id join o in _db.Users on n.UserId equals o.Id join p in _db.Posts on n.PostId equals p.Id select new { Name = o.UserName, Photo = o.UserPhoto, ID = n.UserId, PID = n.PostId, p.PostText, n.Time, Comment = n.Comments }).ToList().OrderByDescending(n => n.ID);
    foreach (var item in qw)
    {
        Comments mycomments = new Comments()
        {
            PId = item.PID,
            UserName = item.Name,
            UserPhoto = item.Photo,
            CommentText = item.PostText,
            Commenttime = item.Time
        };
        List2.Add(mycomments);
    }
    ViewData["comments"] = List2;
    
    return View(posts);
}

View:

foreach (var item in (dynamic)ViewData["likes"])
{
    if (item.Posttext == null)
    {
        var trim = item.Posttext.Substring(0, 5) + "...";
        item.Posttext = "";
    }
    else
    {
        var trim = item.Posttext + " ";
        item.Posttext = trim;
    }
    <li>
        <a href="~/Profile/Index">
            <img class="img-responsive center-block" src="~/Images/@item.UserPhoto" width="40" height="40" />
            <p style="color:black"><b>@item.UserName</b> liked your post @item.Posttext </p>
           <img width="16" height="16" src="@Url.Content("~/Images/like-128.png")" />
           <span style="color:black"> @item.Liketime</span>
        </a>
    </li>
}
foreach (var item in (dynamic)ViewData["comments"])
{
    // trim here
    <li>
        <a href="~/Profile/Index">
            <img class="img-responsive center-block" src="~/Images/@item.UserPhoto" width="40" height="40" />
            <p style="color:black"><b>@item.UserName</b> commented on your post </p>
            <img width="16" height="16" src="@Url.Content("~/Images/Custom-Icon-Design-Flatastic-1-Comment (1).ico")" />
            <span style="color:black"> @item.Commenttime</span>
        </a>
    </li>
}

However, I do not want to print List2 after List1. Instead, I want to print them based on their respective Time properties. If a model from List1 was inserted first, it should be printed first, followed by models from List2 until the end.

Answer №1

To showcase a combined list of Likes and Comments, ordered by Time, it is recommended to create a view model for projecting queries, merging them into one collection, and then sorting based on Time.

Considering the provided view, the required view model would be

public class ResponseVM
{
    public string Name { get; set; }
    public string Photo { get; set; }
    public string Message { get; set; }
    public string Image { get; set; }
    [DisplayFormat(DataFormatString = "{0:...}")] // your format
    public DateTime Time { get; set; }
}

If these are associated with a parent model such as Post, another model would be needed:

public class PostVM
{
    .... // include necessary Post properties for the view
    public IEnumerable<ResponseVM> Responses { get; set; }
}

The GET method implementation would look like this:

var likes = (from n in _db.PostLikes where ....).ToList().Select(x => new ResponseVM()
{
    Name = x.Name,
    Photo = Url.Content(String.Format("~/Images/{0}", x.Photo)),
    Message = String.Format(" liked your post {0}", x.PostText), // refer to notes below
    Image = Url.Content("~/Images/like-128.png"),
    Time = x.Time
});

var comments = (from n in _db.PostComments where ...).ToList().Select(x => new ResponseVM()
{
    .... // similar to above, adjust Message and Image properties accordingly
});
// Combine and order
var responses = likes.Concat(comments).OrderBy(x => x.Time);
PostVM model = new PostVM()
{
    ....
    Responses = responses
};
return View(model);

The corresponding view template would be

@model PostVM
....
<ul>
    @foreach(var response in Model.Responses)
    {
        <li>
            <a href="~/Profile/Index">
                <img class="img-responsive center-block" src="@response.Photo" width="40" height="40" />
                <p style="color:black"><b>@item.Name</b>@response.Message</p>
                <img width="16" height="16" src="@reponse.Image" />
                <span style="color:black">@Html.DisplayFor(m => response.Time</span>
            </a>
        </li>
    }
</ul>

Note: The purpose of the 'trim' code in the view is unclear. In the if block, the variable var trim = ... is assigned but not utilized, while setting Posttext to an empty string serves no purpose. Similarly, the actions taken in the else block seem unnecessary. Such logic should ideally reside in the controller rather than cluttering the view.

Answer №2

To effectively run through both arrays concurrently and select the object with a lower time compared to the other, you must maintain the current index of each array.

There are two approaches you can take:

1) Assume that you have organized and prepared two lists - one for Comments and one for Likes. You will choose the earliest comment/like and add it to the results list:

List<Comments> lComments = someList.OrderBy(a => a.Commenttime);
List<Likes> lLikes = someList2.OrderBy(a => a.Liketime);
List<object> lResults = new List<object>();

int iComment = 0, iLike = 0;
for(int i = 0; i < lComments.Count() + lLikes.Count(); i++)
{
    if(lComments.Count() >= iComment)
    {
        lResults.Add(lLikes[iLike++]);
        continue;
    }

    if(lLikes.Count() >= iLike )
    {
        lResults.Add(lComments[iComment++]);
        continue;
    }

    if(lLikes[iLike].Liketime > lComments[iComment].Commenttime)
        lResults.Add(lComments[iComment++]);
    else
        lResults.Add(lLikes[iLike++]);
}

2) Another method involves utilizing the IComparable<T> interface where Likes and Comments can be compared. By implementing this interface, sorting these elements becomes more straightforward. Merge all objects from Comments and Likes into one list/array, then sort them:

public class Likes : IComparable<T>
{
    public int CompareTo(object obj)
    {
        if(obj is Comments)
            return this.Liketime.CompareTo((obj as Comments).Commenttime);
        if(obj is Likes)
            return this.Liketime.CompareTo((obj as Likes).Liketime);
        throw new NotSupportedException();
    }
}

public class Comments: IComparable<T>
{
    public int CompareTo(object obj)
    {
        if(obj is Comments)
            return this.Commenttime.CompareTo((obj as Comments).Commenttime);
        if(obj is Likes)
            return this.Commenttime.CompareTo((obj as Likes).Liketime);
        throw new NotSupportedException();
    }
}

List<Comments> lComments = someList.OrderBy(a => a.Commenttime);
List<Likes> lLikes = someList2.OrderBy(a => a.Liketime);
List<object> lResults = new List<object>(lComments);
lResults.AddRange(lLikes);
lResults.Sort();

Please consider that certain security checks such as null reference checks have been omitted.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

When incorporating CSS with Bootstrap, it may not always have a visible impact on the

As a newcomer to using Bootstrap, I recently created a webpage with Bootstrap3. However, I encountered an issue when trying to apply two classes to the same element, as the CSS was not being applied: Here is the HTML code snippet: <div class="col-md-4 ...

What are the steps for incorporating information into a designated PhpMyAdmin account?

Currently, I am experimenting with HTML and Php. The website is quite simple at the moment and lacks adequate security measures. My objective is to update a specific user's competition field in the users table located within the authentication folder ...

How can Angular be used to show text without the accompanying HTML tags?

I have a string saved in localStorage that includes HTML tags because I am using ngx-quill (Angular Rich Text Editor) which saves the data in HTML format. Here is a preview of my localStorage: https://i.sstatic.net/NCSgJ.png As shown in the image above, ...

Is there a way for me to include an additional field in the username and password section for creating and authenticating accounts using ASP.NET Identity?

In order to register and authenticate users, we require more than just a username and password for authentication. This is because the username used is their school registration number, and with multiple schools being enrolled on our platform, there could ...

What would be the JavaScript version of the below jQuery code?

I am interested in creating a spinning wheel where instead of the entire wheel rotating, only the pointer rotates. I currently have a jQuery code snippet that achieves this effect, but I am looking to convert it into JavaScript. Current jQuery code: $( d ...

Accessing variables within a frame using JavaScript.Is there a way to access variables within

I am having trouble accessing a Frame that is included within a frameset. The structure looks like this: IFRAME \ FRAMESET \FRAMESET \ FRAME I have been struggling to find a solution, I can only access the iframe ...

What is the best way to fill in predetermined HTML with information using jQuery?

Currently, I am working with several ajax forms that allow me to add rows of data dynamically using ajax. While the form submission is functioning correctly, I am having trouble figuring out the best way to append the newly inserted data into the database. ...

Is the hardware acceleration of the iPhone 4 significantly weaker than that of the iPhone 4s?

My HTML5 web application utilizes hardware acceleration through the CSS3 property translateZ(0). Everything runs smoothly on my 4s device. However, when I try the same application on an iPhone4, the performance drastically decreases and becomes almost un ...

The Bootstrap Grid System Column is Experiencing Issues

Check out my code snippet: I've attempted changing the container class to container-fluid and resizing the page, but no luck. <div class="container"> <div class="row"> <!--Product: banana split--> ...

What is the best way to insert images into a database?

I am currently working on an internship project that requires me to include an image when adding an employee to my table. https://i.stack.imgur.com/xif58.png https://i.stack.imgur.com/wDkY7.png We are using AngularJS on the front end and ASP.NET Core 3. ...

How to Apply CSSResource to Customize a GWT Hyperlink

Hello, I am looking to enhance the visual appeal of my web application using GWT CSSResource. One thing that I am struggling with is styling a simple hyperlink. In traditional CSS, I would typically do the following: a{color: #somecolor} a:hover{color: ...

Switching the order of elements in a column using Flexbox

Here is the grid layout on PC: https://i.sstatic.net/4HRvd.png And here is the grid layout on mobile devices: https://i.sstatic.net/URBjb.png I am looking to rearrange the order and layout of the grid. I have tried using flexbox, but I need to group B an ...

Difficulties encountered with CSS transitions when using the background

I stumbled upon some interesting examples on Stack Overflow about the fade effect on link hover. Curious, I decided to try it out myself and created this JSFiddle. <div class="fade"/> .fade { -o-transition: 0.3s; -moz-transition: 0.3s; -khtml-tran ...

Fetching a DataSet from a Web Api using the GET method

Previously, my code was functioning correctly and returning the proper object type Using jquery: $(document).ready(function () { jQuery.support.cors = true; $.ajax({ url: '/api/News/5', type: 'GET&a ...

Troubles arising from UTF-8 encoded post data on Windows Phone platform

I'm currently working on a Windows Phone app and I need to send a JSON string to the server in UTF8 encoded format. Here is my approach: private void RequestStreamCallBack(IAsyncResult ar) { try { HttpWebRequest re ...

Combining HTML and CSS into a single line using Node.js for optimization

Is there a way to minimize HTML and CSS code into a single line using Node.js? For instance <style media='screen' type='text/css'> .text { padding: 1px 1px 1px 1px; font-size: 12px; } </style> < ...

The JQuery chosen dropdown experiences a visual issue when placed inside a scrollbar, appearing to be "cut

Good day, I've been using the jQuery "chosen" plugin for a dropdown menu, but I encountered an issue with it being located in a scrollable area. The problem is that the dropdown items are getting cut off by the outer div element. I have provided a si ...

Is the "position: sticky" feature functioning correctly, or is there a slight vibrating or dancing effect when users scroll through the Ionic app? How can we eliminate this issue specifically on iOS

Looking for suggestions on this problem - the position sticky is functioning correctly, but there seems to be a slight vibration or dancing effect when users scroll in the Ionic app. Any ideas on how to eliminate this issue specifically on iOS devices? & ...

What is the best way to retrieve the value from local storage?

const value = document.getElementById("demo").getAttribute('value'); if(typeof(Storage)!=="undefined") { alert(value); localStorage.setItem("GetData", value); alert(localStorage.getItem("GetData")); } function loading() { alert("coming" ...

Utilize the DB object only once the DbContext has been properly disposed in Entity Framework

Is it possible to continue using an object retrieved from DbContext even after disposing the DbContext in Entity Framework? Consider the scenario below: class partial DBUser { public string Username { get; set; } } DBUser myUser; using (var context ...