this should be a stupid problem but i dont know where to start,so i'll ask here.i've got a class named Routing which is binded to a datagrid. Inside this class theres an object from another class:
public class Routing : INotifyPropertyChanged
{
public int Sequenza { get; set; }
private ObservableCollection<Prodotti> availableProducts;
public ObservableCollection<Prodotti> AvailableProducts
{
get { return availableProducts; }
set
{
if (availableProducts != value)
{
availableProducts = value;
OnPropertyChanged("AvailableProducts");
}
}
}
private Prodotti product;
public Prodotti Product
{
get { return product; }
set
{
if (product != value)
{
product = value;
UpdateAvailableCosts();
OnPropertyChanged("Product");
}
}
}
}
and then the Product class:
public class Prodotti
{
public int Product_id { get; set; }
public string Product_description { get; set; }
public int Product_treshold { get; set; }
}
Everything works as intended,and if i just declare the "Sequenza = 1" in the routing the datagrid adds the 1 in the first row/column. But i would like to add more initial values,maybe based on data present in the database. but i cant come up with the constructor for it
Routes.Add(new Routing { Sequenza = 1,Prodotti=... });
Routes.Add(new Routing { Sequenza = 1,Prodotti= new Prodotti{Product_id =1, Product_description = "str", Product_treshold =1} });
Related
I use AutoMapper 8.1.0 in a asp.net core project. I have an Automapper mapping that doesn't work as I expected. I reproduced the configuration so you can test it by yourself. So I have an ExpenseReport with a collection of ExpenseReportItem and this one with another collection. I have to keep the data of eTaxCollection after the mapping, but they are lost in the process.
So the question is why values of eTaxCollections are lost after calling _mapper.Map(vmodel, model) and how can I keep them?
The ignore attribute don't work. I also tried UseDestinationValue(). I lost 2 days trying to figure it out and I'm exhausted.
public void WeatherForecasts()
{
int[] excludeTaxes = new int[] { 2 };
var vmodel = new ExpenseReportCreateEditModel();
vmodel.Expenses.Add(new ExpenseReportItemModel()
{
ExcludeTaxIds = excludeTaxes,
Total = 12,
Id = 1
});
// fetch from bd
var model = new ExpenseReport();
// values will be lost after _mapper.Map...
var eTaxCollections = new HashSet<ExcludeExpenseReportItemTax>();
eTaxCollections.Add(new ExcludeExpenseReportItemTax()
{
TaxId = 1,
ExpenseReportItemId = 1
});
model.Items.Add(new ExpenseReportItem()
{
ExcludeTaxes = eTaxCollections,
ExpenseReportId = 1,
Id = 9
});
_mapper.Map(vmodel, model);
}
public class ExpenseReportCreateEditModelProfile : Profile
{
public ExpenseReportCreateEditModelProfile()
{
CreateMap<ExpenseReportCreateEditModel, ExpenseReport>()
.ForMember(d => d.Items, s => s.MapFrom(m => m.Expenses));
}
}
public class ExpenseReportItemModelProfile : Profile
{
public ExpenseReportItemModelProfile()
{
CreateMap<ExpenseReportItemModel, ExpenseReportItem>()
.ForMember(d => d.ExcludeTaxes, s => s.Ignore()); // <<<==== data are lost
}
}
public class ExpenseReportCreateEditModel
{
public int Id { get; set; }
public ICollection<ExpenseReportItemModel> Expenses { get; set; }
public ExpenseReportCreateEditModel()
{
Expenses = new HashSet<ExpenseReportItemModel>();
}
}
public class ExpenseReportItemModel
{
public int Id { get; set; }
public ICollection<int> ExcludeTaxIds { get; set; }
public decimal Total { get; set; }
public ExpenseReportItemModel()
{
ExcludeTaxIds = new HashSet<int>();
}
}
public class ExpenseReport
{
public int Id { get; set; }
public virtual ICollection<ExpenseReportItem> Items { get; set; }
public ExpenseReport()
{
Items = new HashSet<ExpenseReportItem>();
}
}
public class ExpenseReportItem
{
public int Id { get; set; }
public int ExpenseReportId { get; set; }
public virtual ICollection<ExcludeExpenseReportItemTax> ExcludeTaxes { get; set; }
public ExpenseReportItem()
{
ExcludeTaxes = new HashSet<ExcludeExpenseReportItemTax>();
}
}
public class ExcludeExpenseReportItemTax
{
public int ExpenseReportItemId { get; set; }
public virtual ExpenseReportItem ExpenseReportItem { get; set; }
public int TaxId { get; set; }
}
Thank you for any help
Edit
I execute the execution plan and perhaps this is the problem:
$typeMapDestination = ($dest ?? .New WebApplication1.Controllers.SampleDataController+ExpenseReportItem());
This is only way I can lost the values.
I have to find a solution now
Here the complete execution plan :
.If ($src == null) {
.Default(WebApplication1.Controllers.SampleDataController+ExpenseReportItem)
} .Else {
.Block() {
$typeMapDestination = ($dest ?? .New WebApplication1.Controllers.SampleDataController+ExpenseReportItem());
.Try {
.Block(System.Int32 $resolvedValue) {
.Block() {
$resolvedValue = .If (
$src == null || False
) {
.Default(System.Int32)
} .Else {
$src.Id
};
$typeMapDestination.Id = $resolvedValue
}
}
} .Catch (System.Exception $ex) {
.Block() {
.Throw .New AutoMapper.AutoMapperMappingException(
"Error mapping types.",
$ex,
.Constant<AutoMapper.TypePair>(AutoMapper.TypePair),
.Constant<AutoMapper.TypeMap>(AutoMapper.TypeMap),
.Constant<AutoMapper.PropertyMap>(AutoMapper.PropertyMap));
.Default(System.Int32)
}
};
$typeMapDestination
}
}
So I'm trying to build a small cookbook application using WPF and MVVM light. I've run into a situation where I'm binding a List from the model to the view model. And it works fine for displaying and removing items, but when adding items I couldn't get the display to update.
I came across ObserableCollections which seemed to be just what I wanted, but I'm not sure I'm using them correctly because it seems wrong to be creating a new OC every time. How am I supposed to be retrieving an observable collection when the model is using a list?
Model(s):
public class Recipe
{
public int Id { get; set; }
public string Title { get; set; }
public List<RecipeIngredient> Ingredients { get; set; }
}
public class RecipeIngredient
{
// ... //
}
ViewModel:
public Recipe SelectedRecipe
{
get
{
return this.selectedRecipe;
}
set
{
this.selectedRecipe = value;
RaisePropertyChanged("SelectedRecipe");
RaisePropertyChanged("RecipeIngredients");
}
}
public ObservableCollection<RecipeIngredient> RecipeIngredients
{
get
{
return new ObservableCollection<RecipeIngredient>(selectedRecipe.Ingredients.ToList());
}
}
public RelayCommand<EventArgs> AddIngredientCommand { get; private set; }
public RelayCommand<string> DeleteIngredientCommand { get; private set; }
private void AddIngredient(EventArgs eventArgs)
{
SelectedRecipe.Ingredients.Add(new RecipeIngredient() { Name = "New Ingredient" });
RaisePropertyChanged("RecipeIngredients");
}
private void DeleteIngredient(string name)
{
SelectedRecipe.Ingredients = SelectedRecipe.Ingredients.Where(i => i.Name != name).ToList();
RaisePropertyChanged("RecipeIngredients");
}
public MainViewModel()
{
DBController db = new DBController();
recipes = db.GetRecipeList();
RecipeSelectionChangedCommand = new RelayCommand<SelectionChangedEventArgs>((args) => RecipeSelectionChanged(args));
SaveRecipeCommand = new RelayCommand<EventArgs>((args) => SaveRecipe(args));
AddIngredientCommand = new RelayCommand<EventArgs>((args) => AddIngredient(args));
DeleteIngredientCommand = new RelayCommand<string>((args) => DeleteIngredient(args));
}
Am I way off track here?
Should have read more carefully. If you're displaying the selected recipe's ingredients in an alternate view, you should be using data binding in the view <ListBox ItemsSource="{Binding SelectedRecipe.Ingredients}"/> You could consider using linq to entities (Entity Framework) for ORM..
public class RecipeVM
{
public RecipeVM(Recipe r)
{
recipe = r;
}
Recipe recipe;
public int Id
{
get
{
return recipe.Id;
}
set
{
PropertyChanged("Id");
recipe.id = value;
}
}
public string Title
{
get
{
return recipe.Title;
}
set
{
PropertyChanged("Title");
recipe.Title = value;
}
}
ObservableCollection<RecipeIngredient> ingredients;
public ObservableCollection<RecipeIngredient> Ingredients
{
get
{
if (ingredients == null)
ingredients = new ObservableCollection<RecipeIngredient>(recipe.Ingredients);
return ingredients;
}
set
{
PropertyChanged("Ingredients");
ingredients = value;
}
}
}
You'll need to modify that a bit if you want to keep the collections in sync though..
What should I be calling the "BFactory" below. Its not really a Factory since there is no selection of a concrete class happening, and its not necessarily creating an object each time. Its kind of a Pool but the users do not return the Bs they get to the pool after they are done with them. It could be called a Cache but performance is not the primary intention. The intention is that everyone who is using the same BFactory will get the same B when they pass the same A which starts to sound kind of like a singleton-ish.
public class A
{
public int MyProperty { get; set; }
}
public class B
{
public B(A wrapped)
{
Wrapped = wrapped;
}
public A Wrapped { get; set; }
}
public class BFactory
{
private Dictionary<A,B> _created = new Dictionary<A,B>();
public B GetB(A a)
{
if (_created.ContainsKey(a) == false)
{
_created[a] = new B(a);
}
return _created[a];
}
}
here is a slightly more real example:
The value from MyModel is shown in several locations in the app by binding a TextBlock to the ValueString property of MyViewModel. The user can select to present the value as a percent or a decimal and it should be updated in all locations if it is updated in one.
public class MyModel
{
public int Value { get; set; }
}
public class MyViewModel
{
private readonly MyModel _model;
public MyViewModel(MyModel model)
{
_model = model;
}
public string ValueString
{
get { return string.Format(FormatString, _model.Value); }
}
public string FormatString { get; set; }
}
public class MyViewModelFactory
{
private readonly Dictionary<MyModel, MyViewModel> _created = new Dictionary<MyModel, MyViewModel>();
public MyViewModel GetViewModel(MyModel model)
{
if (_created.ContainsKey(model) == false)
{
_created[model] = new MyViewModel(model);
}
return _created[model];
}
}
I have a table that holds Questions and i also have a table that has the Questions ID listed in an answers table. For sake of duplicate data i only use the id.
My question is how do i populate "in the view" the question based on an ID from the current table. They are already joined by MainQuestionID. I am using DBEntities code first.
Here is my viewModel for the page.
public class AuditFormEdit
{
public Models.MainQuestion MainQuestionID { get; set; }
public ICollection<MainQuestion> mainQuestion { get; set; }
public List<SubcategoryHelper> SubcategoryHelperGet { get; set; }
public class SubcategoryHelper : Models.SubCategory
{
public SubcategoryHelper(Models.SubCategory subCat)
{
this.SubCategoryID = subCat.SubCategoryID;
this.SubcategoryName = subCat.SubcategoryName;
}
}
public Models.MainAnswer MainAnswerInstance { get; set; }
public List<ScoreCardCheckBoxHelper> ScoreCardCheckBoxHelperList { get; set; }
public void InitializeScoreCheckBoxHelperList(List<Models.Score> ScoreList)
{
if (this.ScoreCardCheckBoxHelperList == null)
this.ScoreCardCheckBoxHelperList = new List<ScoreCardCheckBoxHelper>();
if (ScoreList != null
&& this.MainAnswerInstance != null)
{
this.ScoreCardCheckBoxHelperList.Clear();
ScoreCardCheckBoxHelper scoreCardCheckBoxHelper;
string scoreTypes =
string.IsNullOrEmpty(this.MainAnswerInstance.Score) ?
string.Empty : this.MainAnswerInstance.Score;
foreach (Models.Score scoreType in ScoreList)
{
scoreCardCheckBoxHelper = new ScoreCardCheckBoxHelper(scoreType);
if (scoreTypes.Contains(scoreType.ScoreName))
scoreCardCheckBoxHelper.Checked = true;
this.ScoreCardCheckBoxHelperList.Add(scoreCardCheckBoxHelper);
}
}
}
public void PopulateCheckBoxsToScores()
{
this.MainAnswerInstance.Score = string.Empty;
var scoreType = this.ScoreCardCheckBoxHelperList.Where(x => x.Checked)
.Select<ScoreCardCheckBoxHelper, string>(x => x.ScoreName)
.AsEnumerable();
this.MainAnswerInstance.Score = string.Join(", ", scoreType);
}
public class ScoreCardCheckBoxHelper : Models.Score
{
public bool Checked { get; set; }
public ScoreCardCheckBoxHelper() : base() { }
public ScoreCardCheckBoxHelper(Models.Score score)
{
this.ScoreID = score.ScoreID;
this.ScoreName = score.ScoreName;
}
}
}
AS you can see i am calling out an ICollection for the MainQuestions but i am not sure how to populate the questions. They also have to populate based on a sectionID.
Revised 2:51 9-21-2012
Or how would i relate the two if i displayed the list of questions and then when answering it would update the answers table and not the current shown table.
I have the following abstract class:
public abstract class TemplateBase
{
public abstract string TemplateName { get; }
public string RuntimeTypeName { get { return GetType().FullName; } }
public abstract List<AreaContainer> TemplateAreas { get; }
}
then these 2 inherited classes:
public class SingleColumnTemplate : TemplateBase
{
public override string TemplateName { get { return "Single column"; } }
public AreaContainer CenterColumn { get; private set; }
public SingleColumnTemplate()
{
this.CenterColumn = new AreaContainer("Middle");
}
private List<AreaContainer> templateAreas;
public override List<AreaContainer> TemplateAreas
{
get
{
if (this.templateAreas == null)
{
this.templateAreas = new List<AreaContainer>() { this.CenterColumn };
}
return this.templateAreas;
}
}
}
and
public class TwoColumnTemplate : TemplateBase
{
public override string TemplateName { get { return "Two column"; } }
public AreaContainer LeftColumn { get; private set; }
public AreaContainer RightColumn { get; private set; }
public TwoColumnTemplate()
{
LeftColumn = new AreaContainer("Left");
RightColumn = new AreaContainer("Right");
}
private List<AreaContainer> templateAreas;
public override List<AreaContainer> TemplateAreas
{
get
{
if (this.templateAreas == null)
{
this.templateAreas = new List<AreaContainer>() { this.LeftColumn, this.RightColumn };
}
return this.templateAreas;
}
}
}
I also have this class that is my model for editing:
public class ContentPage
{
public virtual int ContentPageId { get; set; }
public virtual string Title { get; set; }
public TemplateBase Template { get; set; }
}
Question:
for my ActionResults I have the following:
[HttpGet]
public ActionResult Edit()
{
var row = new ContentPage();
var template = new TwoColumnTemplate();
// Areas
HtmlArea html_left = new HtmlArea();
html_left.HtmlContent = "left area html content";
HtmlArea html_right = new HtmlArea();
html_right.HtmlContent = "right area html content";
template.LeftColumn.Areas.Add(html_left);
template.RightColumn.Areas.Add(html_right);
row.Template = template;
return View(row);
}
[HttpPost]
[ValidateInput(false)]
public ActionResult Edit(ContentPage row)
{
// Here i could loop through List -TemplateAreas and save each template Area to Db. I guess that would work
return this.View(row);
}
Question:
For HttpGet- how would I load row Template from the database? since it could be SingleColumnClass or TwoColumnClass.
how would my ViewModel look like to solve this?
thanks
You can write your own Model Binder that is responsible for binding TemplateBase. You will still need to have a way of knowing (in the model binder) which type you will be using a runtime, but you can always delegate that to a factory or service locator of some sort. I did a quick google search and here is a blog post I found that gives you some information for making a model binder for a similar scenario:
http://weblogs.asp.net/bhaskarghosh/archive/2009/07/08/7143564.aspx
EDIT: The blog leaves out how you tell MVC about your model binder. When the application starts, you can add your model binder to System.Web.Mvc.ModelBinders.Binders
HTH
You need to know the template type in you controller, so you can pass a parameter from the view to the controller, indicating the type (SingleColumn or TwoColumn). You could do this witn a Enum:
public enum TemplateType
{
SingleColumn,
TwoColumn
}
[HttpGet]
public ActionResult Edit(TemplateType templateType)
{
var row = new ContentPage();
TemplateBase template;
if (templateType == TemplateType.SingleColumn)
{
template = new SingleColumnTemplate();
}
else
{
template = new TwoColumnTemplate();
}
...
return View(row);
}
When you create the action link from your view you can specify:
<%= Html.ActionLink("Edit",
"Edit",
"YouController",
new
{
// singlecolumn or twocolumn
// depending on your concrete view
TemplateType = TemplateType.xxx
},
null);
I wonder if you could do something like this?
[HttpGet]
public ActionResult Edit(TemplateType templateType)
{
var row = new ContentPage();
TemplateBase template = (TemplateBase)Activator.CreateInstance(templateType);
...
return View(row);
}
templateType would have to be the exact name of your inherited classes (you can ignore case)