TAHATEMURII TAHATEMURII - 19 days ago 6
CSS Question

Print two List of model type by time

I have 2 List of model type that is initialized in controller and inserted value in them and then assign these list object to Viewdata so that I can iterate through this list using forach.But problem is that Model of these 2 list have Property Time so that I want to print these 2 List orderby their time.
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>
}


But I don't want to print
List2
after
List1
. I want to print them by
Time
if
list1
model inserted first it should print if
list2
it should print until end of both list.

Answer

If you want to display Likes and Comments in one list, ordered by Time, then create a view model so that you can project your queries to that view model, concatenate them to one collection and then sort by Time.

Based on the view you have shown, your view model will 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; }
}

Assuming that your displaying these associated with a parent model (say Post), then you would also have

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

The GET method will then be

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), // see 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()
{
    .... // as above except adjust Message and Image properties
});
// Combine and order
var responses = likes.Concat(comments).OrderBy(x => x.Time);
PostVM model = new PostVM()
{
    ....
    Responses = responses
};
return View(model);

And the view will 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>

Side note: Its not clear what your trying to do with your 'trim' code in your view. In the if block you set a variable var trim = ... but never use it, and then you set Posttext to an empty string which is pointless. In the else block you appear to be just adding space to the end which is unnecessary. In any case, that type of code belongs in the controller, not the view.

Comments