I have defined a model as follows:
public class UserDetails
{
public int Id { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public List<Transport> TransportModel { get; set; }
}
Based on the above model, I have instantiated a list that contains hard coded values for testing purposes.
Further, I am dynamically populating buttons based on the TransportModel values on a XAML page as follows:
StackLayout stack = new StackLayout();
foreach (var t in user.TransportModel)
{
// Here I am looping to access data in the TransportModel
Button btn = new Button();
btn.Text = t.Name;
btn.SetBinding(Button.CommandProperty, new Binding("ShowCommandParameter"));
btn.CommandParameter = user.TransportModel; // if this correct ?
stack.Children.Add(btn);
}
And I have the following ViewModel:
public TransportViewModel()
{
ShowCommandParameter = new Command<UserDetails>(Show);
}
public void Show(UserDetails param)
{
// I want to access properties of TransportModel here..
}
The issue that I am having is that I want to pass two parameters in the CommandParameter. And I want to access these values within the Show method.
Could someone please help me on this ? I'm totally stuck.
since each button only applies to a specific Transport, you want to pass a Transport object as your CommandParameter
foreach (var t in user.TransportModel)
{
...
btn.CommandParameter = t;
...
}
then
public TransportViewModel()
{
ShowCommandParameter = new Command<Transport>(Show);
}
public void Show(Transport param)
{
// param contains the selected Transport
}
Related
I create a static class that includes the definition of global variables and functions, but maybe it is wrong.
I need to crete a shopping cart, after refreshing,the content shouldn't be lost.
In staic class A, I create a staic variables ObservableCollection Collection1 and Collection2(Collection1 have children but Collection2) and staic functions Refresh() used to refresh Collection1.
In dynamic class B, I get some children and add them to Collection2, then use A.Refresh(), in the process of refreshing, if the new data have same id as any one in old Collection2, add it in new Collection2.
public class Model
{
public Guid Id{ get; set; }
public string Name{ get; set; }
}
public static class A
{
public static ObservableCollection<Model> Collection1 { get; set; } = new ObservableCollection<Model>();
public static ObservableCollection<Model> Collection2 { get; set; } = new ObservableCollection<Model>();
public static Refresh()
{
var uidList = Collection2.Select(x => x.Id).ToList();
Collection1.Clear();
Collection2.Clear();
foreach (var item in dataFromServer)
{
var newModel = new Model{Id = item.Id};
Collection1.Add(newModel);
if(uidList.Contains(item.Id))
{
Collection2.Add(newModel);
}
}
}
}
public class B
{
public B()
{
A.Refresh();
}
public AddToCart(Guid id)
{
var model = A.Collection1.First(x=>x.Id == id);
if (!A.Collection2.Contains(model))
{
A.Collection2.Add(model);
}
}
public Refresh()
{
A.Refresh();
}
}
I used B.AddToCart(AAAA) to add a child to Collection2,then used B.Refresh(),now I have new data form server,a new object(Id is AAAA) in Collection1 and Collection2.Then I used B.AddToCart(AAAA) again,now Collection2 have two children with same Id and Name,even I change one of the,the other one's name changed too.It's meaning there are same two object in Collection2 right?But why does A.Collection2.Contains(model) return false?I used Object.ReferenceEquals to check the two children,the result is false,too.
I konw Collection2.Any(x=>x.Id==id) can be worked,I just want to konw how it happened.
Edit:I create a demo,but he problem did not recur,maybe something wrong in other part.
You need to implement IEquatable<Model> on your Model class.
This is a duplicate question, REF: ObservableCollection.Contains() Doesn't Work Correctly
Sorry if this is a simple question but if I want to have a list inside a model, and later access and set the values of the list?
Say my main model looks like this:
public class StartPageModel : IPageViewModel<StartPage>
{
public IList<ListContent> ListContent { get; set; }
public StartPage CurrentPage { get; set; }
}
public class ListContent
{
public IList<ListElement> ArticleListContent { get; set; }
public IList<ListElement> InsightListContent { get; set; }
}
How can I set the ArticleListContent list to a value by referencing the parent model?
public ActionResult Index(StartPage currentPage)
{
var model = new StartPageModel(currentPage);
model.ListContent.ArticleListContent = GetListContent(currentPage.ArticleCollection);
}
However this returns the error:
IList does not contain a definition for 'ArticleListContent'
I'm not sure you require a collection of ListContent in your StartPageModel, correct me if I'm wrong.
Change
public IList<ListContent> ListContent { get; set; }
to
public ListContent ListContent { get; set; }
And provided ListContent is initialized, your assignment will work.
It's because it's referencing the List of ListContent, not an individual item in that list. Here's some examples:
var model = new StartPageModel(currentPage);
model.ListContent[0].ArticleListContent = GetListContent(currentPage.ArticleCollection); // Access first in list
model.ListContent[1].ArticleListContent = GetListContent(currentPage.ArticleCollection); // Access secondin list
model.ListContent.First().ArticleListContent = GetListContent(currentPage.ArticleCollection); // Access first in list using Linq
This is my first question here and I'm new to WPF/MVVM.
What I'm trying to do is display a multi-column listview that holds the results returned from a stored procedure.
I'm doing my best to implement MVVM and this is where I'm having trouble.
I have a model (SL_ID is the PK and not nullable in the database):
public class mJob_Select_OrderList
{
public int SL_ID { get; set; }
public string E32JobNumber { get; set; }
public string E32_CLIENT { get; set; }
public string SL_DESCRIPTION { get; set; }
public string E32_DESCRIPTION { get; set; }
}
and then I have a view model:
public class vmJob_Select : vmMain
{
#region Members
Models.mJob_Select _mJobSelectSettings;
public SLEVEN_CLASS.dbSLEVENDataContext _dc;
#endregion
#region Constructors
public vmJob_Select()
{
_dc = new SLEVEN_CLASS.dbSLEVENDataContext();
_mJobSelectSettings = new Models.mJob_Select { EnvironmentID = 1 };
//EnvironmentList
var dsEnvironmentList = (from el in _dc.vw_EnvironmentLists orderby el.ENV_ID select new mJob_Select_Environment { ENV_ID = el.ENV_ID, Environment = el.Environment, IMAGE_RESOURCE = el.IMAGE_RESOURCE });
EnvironmentList = new ObservableCollection<mJob_Select_Environment>(dsEnvironmentList);
//Orders List
var dsSLEVENOrders = _dc.get_SLORDER_List(SelectedEnvironmentID).ToList();
SelectOrderList = new List<mJob_Select_OrderList>(dsSLEVENOrders);
}
#endregion
#region Properties
public Models.mJob_Select mJobSelectSettings { get { return _mJobSelectSettings; } set { _mJobSelectSettings = value; } }
public int SelectedEnvironmentID { get { return mJobSelectSettings.EnvironmentID; } set { if (mJobSelectSettings.EnvironmentID != value) { mJobSelectSettings.EnvironmentID = value; RaisePropertyChanged("EnvironmentID"); } } }
public ObservableCollection<mJob_Select_Environment> EnvironmentList { get; set; }
public List<mJob_Select_OrderList> SelectOrderList { get; set; }
}
So basically EnvironmentList is pulled from a view in the database and I can populate an ObservableCollection successfully. The SelectedOrderList is the result of a stored procedure and I'm trying to load this result into a list object of some sort.
The error I'm getting is
Cannot convert from 'System.Collections.Generic.List' to 'int'
I was able to implement this successfully in the code behind on the view but I'm trying to adhere to MVVM and making my ViewModel do the work.
using (SLEVEN_CLASS.dbSLEVENDataContext dbSLEVEN = new SLEVEN_CLASS.dbSLEVENDataContext())
{
var dsSLEVENOrders = dbSLEVEN.get_SLORDER_List(intENVID);
lvSlevenJobs.ItemsSource = dsSLEVENOrders;
lvSlevenJobs.SelectedValuePath = "SL_ID";
}
I've been searching and trying to figure this out for awhile now and I've tried to implement some solutions that I've found here and there to no avail. One involved looping through the IResult and adding each row to the model another suggested building a more complex linq query instead of a stored procedure. None of these options are out of the question. Is there a generally accepted method for performing this task?
Thanks in advance to any answers/suggestions you can provide!
//EDIT//
I believe I've found my solution. I was trying to return my SPROC results to a model that I created but when using LINQ a Model is created automatically called Procedure Name + 'Result'.
I declared my list to utilize the 'Result' model like so:
public List<get_SLORDER_ListResult> SelectOrderList { get; set; }
List<get_SLORDER_ListResult> lstSLEVENOrders = _dc.get_SLORDER_List(SelectedEnvironmentID).ToList<get_SLORDER_ListResult>();
SelectOrderList = new List<get_SLORDER_ListResult>(lstSLEVENOrders);
I then bound my ListView to SelectOrderList.
I was trying to populate a DevExpress gridview with some datas.
Let's say we have two classes :
public class ObjectA
{
public string Name { get; set; }
public List<ObjectB> Details1 { get; set; }
public List<ObjectB> Details2 { get; set; }
}
public class ObjectB
{
public string Name { get; set; }
public string Description { get; set; }
}
And a form created like that :
private List<ObjectA> datas;
public Form1()
{
InitializeComponent();
// Fill data
datas = ...
// Set datasource
this.gridControl1.DataSource = datas;
this.gridView1.BestFitColumns();
this.SetRelation();
}
private void SetRelation()
{
GridView customPatternView = new GridView(gridControl1);
customPatternView.Columns.AddField("Name").VisibleIndex = 0;
customPatternView.Columns.AddField("Description").VisibleIndex = 1;
this.gridControl1.LevelTree.Nodes.Add("CustomRelation", customPatternView);
}
This code is working well but I'm obly able to display Details1 in the details view.
How can I do to display only Details2 ?
Thanks
You need one GridView for each detail view.
gridControl1.LevelTree.Nodes.Add("Details1", customPatternView);
gridControl1.LevelTree.Nodes.Add("Details2", customPatternView);
You can use GridControl.ShowOnlyPredefinedDetails property. If you set this property to true then the GridControl displays only the relationships that exist in the LevelTree. Also, use the name of your child list property as relation name in GridControl.LevelTree.Nodes.Add method.
Here is example:
private void SetRelation()
{
var customPatternView = new GridView(gridControl1);
customPatternView.Columns.AddField("Name").VisibleIndex = 0;
customPatternView.Columns.AddField("Description").VisibleIndex = 1;
this.gridControl1.LevelTree.Nodes.Add("Details2", customPatternView);
this.gridControl1.ShowOnlyPredefinedDetails = true;
}
I'm trying to make a streamlined viewmodel that I can dynamically generate some html based off of. However, I don't quite understand how (or if it's even possible) to create a viewmodel with a dynamic value.
My viewmodel:
public class DataGridViewModel<T>
{
public List<T> DataList { get; set; }
public List<HeaderValue> DataHeaders { get; set; }
public DataGridViewModel(List<T> dataIn)
{
DataList = dataIn;
SetHeaders();
}
public void SetHeaders()
{
//Build a list of column headers based on [Display] attribute
DataHeaders = new List<HeaderValue>();
var t = DataList.First().GetType();
foreach (var prop in t.GetProperties())
{
var gridattr = prop.GetCustomAttributes(false).FirstOrDefault(x => x is DisplayAttribute);
var head = gridattr == null ? "" : (string) gridattr.GetType().GetProperty("Name").GetValue(gridattr);
var visible = gridattr != null;
DataHeaders.Add(new HeaderValue()
{
Header = head,
Visible = visible,
Property = prop.Name
});
}
}
}
My controller:
var docdto = DocumentService.FetchDocuments(); //Returns IQueryable<DocumentDTO>
var vm = new DataGridViewModel<DocumentDto>(docdto.ToList());
return View(vm);
DocumentDTO:
public class DocumentDto
{
public Int32 DocumentId { get; set; }
[Display(Name = "Category")]
public string CategoryName { get; set; }
}
//These could be very different, based on the table they're modeled after.
View:
#model DataGridViewModel<T>
#foreach(var header in Model.DataHeaders)
{
<h1>#header.Property</h1>
}
The issue I'm having is, it seems the view cannot use a generic or dynamic value, and must be assigned to a base class. The problem then is that the DTOs are all very different.
Is this possible to do with Razor?
Thank you for your time :)