Reputation: 16705
I currently have the following code in the HomeController of my MVC project:
public class HomeController : Controller
{
public ActionResult Index()
{
MyDataContext dc = new MyDataContext();
IQueryable<Table1Data> j =
from n in dc.Table1
select n;
return View(j);
}
So that works okay, but now I want to pass a second table through to the same view. So I was thinking I should be able to do something like this:
public class HomeController : Controller
{
public ActionResult Index()
{
MyDataContext dc = new MyDataContext();
IQueryable<Table1Data> j =
from n in dc.Table1
select n;
IQueryable<Table2Data> l =
from k in dc.Table2
select k;
return View(j, l);
}
Is there a way to have the view accept two models like this or, alternatively, a way to merge the two result sets (the two tables are not linked in any way?
Upvotes: 9
Views: 25772
Reputation: 56
I solved the problem by creating a list of 'tables' and passing this to my view model. This is essentially a list of a list of TransactionEntities. FYI, my solution was named DAL, and in the models I created a TransactionEntity to represent a transaction.
private TransactionEntity te;
private IEnumerable<TransactionEntity> tel1; // A list of TransactionEntities
private IEnumerable<TransactionEntity> tel2;
private IEnumerable<TransactionEntity> tel3;
private IEnumerable<IEnumerable<TransactionEntity>> telCollection;
I populate the transaction entity lists (tel1, tel2, tel3) with my te 'rows', then add the three 'tel' objects (like a table essentially) to my telCollection and assign this to my ViewData.Model.
telCollection = new List<IEnumerable<TransactionEntity>>();
telCollection = telCollection.Concat(new[] { tel1 });
telCollection = telCollection.Concat(new[] { tel2 });
telCollection = telCollection.Concat(new[] { tel3 });
ViewData.Model = telCollection;
return View();
In the ASPX file, I then get the list and iterate through each 'table' (ElementAt(#)), creating three different columns, one for each of the tal 'tables'. BTW, you can ignore the counter variable.
<td>
<% int counter = 0; %>
<% IEnumerable<IEnumerable<DAL.Models.TransactionEntity>> tranlist =
(IEnumerable<IEnumerable<DAL.Models.TransactionEntity>>)ViewData.Model; %>
<% foreach (DAL.Models.TransactionEntity te in tranlist.ElementAt(0))
{.... create rows/columns as needed for the data in a HTML sub-table ......} %>
</td>
<td>
<% counter = 0; %>
<% foreach (DAL.Models.TransactionEntity te in tranlist.ElementAt(1))
{..........} %>
</td>
<td>
<% counter = 0; %>
<% foreach (DAL.Models.TransactionEntity te in tranlist.ElementAt(2))
{..........} %>
</td>
Upvotes: 2
Reputation: 23613
Yes there is, but not quite like that. The way to do what you wish to do is to create a custom ViewModel class. This class (MyPageViewModel) would have two (or more) properties, one for each of your objects. In your view, you would access them using Model.Table1Data
and Model.Table2Data
.
A custom ViewModel class is very simple:
public class MyPageViewModel
{
public IQueryable<Table1Data> Table1Data { get; set; }
public IQueryable<Table2Data> Table2Data { get; set; }
}
You view would need to be strongly typed to this custom ViewModel class.
<%@ Page Title="MyPage" MasterPageFile="~/Application/Master Pages/Site.Master"
Inherits="System.Web.Mvc.ViewPage(Of MyAppNamespace.MyPageViewModel)" %>
Don't try to type that youself; easier to create a new view and check "strongly typed" view, and specify your New Custom Viewmodel class.
Then your action Controller method would be:
public class HomeController : Controller
{
public ActionResult Index()
{
MyDataContext dc = new MyDataContext();
MyPageViewModel vm = new MyPageViewModel();
vm.Table1Data = from n in dc.Table1
select n;
vm.Table1Data = from k in dc.Table2
select k;
return View(vm);
}
}
Upvotes: 17
Reputation: 14610
You will probably have to use ViewModel. You define class, that will contain instances of both classes you want (+ any other additional properties), and then you use this as a model.
class NewViewModel {
Table1 T1 {get;set;}
Table2 T2 {get;set;}
int Anything {get;set;}
}
Then you just prepare collection of these ViewModel classes and later access instances of them like:
NewViewModel m = new NewViewModel();
var a = m.T1.PropertyA;
var b = m.T2.PropertyB;
etc.. Just merge all entities you need into one class and use this class as your model in Controller and View.
Upvotes: 0
Reputation: 76597
You could make them both into a single ViewModel:
Model Definition:
public class YourModelName
{
public IQueryable<Table1Data> FirstTableData { get; set;}
public IQueryable<Table2Data> SecondTableData { get; set;}
public YourModelName(IQueryable<Table1Data> d1, IQueryable<Table2Data> d2)
{
this.FirstTableData = d1;
this.SecondTableData = d2;
}
}
Usage (in Controller):
public ActionResult Index()
{
MyDataContext dc = new MyDataContext();
IQueryable<Table1Data> j =
from n in dc.Table1
select n;
IQueryable<Table2Data> l =
from k in dc.Table2
select k;
YourModelName model = new YourModelName(j, l);
return View(model);
}
Upvotes: 1
Reputation: 1941
Why don't you add a class in your models for this?
public class MyModel {
public j {get; set;}
public l {get; set;}
}
Then you pass MyModel to the view on the View's Head.
On the controller:
public ActionResult Index() { MyDataContext dc = new MyDataContext();
IQueryable<Table1Data> j =
from n in dc.Table1
select n;
IQueryable<Table2Data> l =
from k in dc.Table2
select k;
MyModel myclass = new MyModel();
myclass.j = j;
myclass.l = l;
return View(myclass);
}
Upvotes: 2
Reputation: 31761
In pre-MVC3 I would have used a ViewModel and add properties for each object you want the view to use. If you're using MVC3 I'd take a look at ViewBag.
A simple view model:
public class SomeViewModel
{
public object Object1 { get; set; }
public string Message { get; set; }
}
Then in your controller you'd pass this to your view:
var vm = new SomeViewModel { Object1 = coolThing, Message = neatMessage };
return View(vm);
Upvotes: 0
Reputation: 986
Yes - create a new class - which you will use as your model - that contains both tables:
public class MyModel {
public IQueryable<Table1Data> Table1Data { get; set; }
public IQueryable<Table2Data> Table2Data { get; set; }
}
Then, in your controller, initialize this class and populate both properties and send it to your view. Then, modify the view to recognize this new type as the view model.
Upvotes: 3