i need to save a List of Objects, The Objects are created from a class i made. what should i do?
i tried the XmlSerializer, and i added the [XmlElement] to the fields i need to be serialized. but it kept giving me "There is an Error in XML Document".
I tried also the DataContractSerializer, and i used the [DataContract] and [DataMember] but it wont save my objects.
both storage classes work for basic elements (int,bool .. etc) but not my objects.
heres my code for saving:
using (IsolatedStorageFile saveGameFile = IsolatedStorageFile.GetUserStoreForApplication())
using (IsolatedStorageFileStream SaveGameStream = new IsolatedStorageFileStream("GemsCollector1.dat", FileMode.OpenOrCreate, saveGameFile))
{
XmlSerializer serializer = new XmlSerializer(typeof(List<Card>));
serializer.Serialize(SaveGameStream, Cards);
}
and this one for loading:
using (IsolatedStorageFile saveGameFile = IsolatedStorageFile.GetUserStoreForApplication())
using (IsolatedStorageFileStream saveGameStream = new IsolatedStorageFileStream("GemsCollector1.dat", FileMode.OpenOrCreate, saveGameFile))
{
if (saveGameStream.Length > 0)
{
XmlSerializer serializer = new XmlSerializer(typeof(List<Card>));
Cards = (List<Card>)serializer.Deserialize(saveGameStream);
}
}
my Card Class:
public class Card
{
[XmlElement]
public CardType CardType { get; set; }
[XmlElement]
public CardColor CardColor { get; set; }
[XmlElement]
public int Value { get; set; }
[XmlElement]
public Vector2 Position { get; set; }
[XmlElement]
public PlayerPosition playerPosition { get; set; }
[XmlElement]
public CardStatus Status { get; set; }
public Rectangle BoundingBox
{
get
{
int width = (playerPosition == PlayerPosition.Left || playerPosition == PlayerPosition.Right) ? 150 : 100;
int height = (playerPosition == PlayerPosition.Left || playerPosition == PlayerPosition.Right) ? 100 : 150;
return new Rectangle((int)Position.X, (int)Position.Y, width, height); ;
}
}
[XmlElement]
public bool isUsed;
public Vector2 endPosition = new Vector2(235,200);
public Rectangle ThrowArea = new Rectangle(235, 200, 350, 120);
[XmlElement]
public string cardTextureName;
private string back = "back";
private static bool ReserveDrag;
[XmlElement]
private Vector2 touchFromCenter;
[XmlElement]
private int touchId;
public Card()
{
}
}
can anybody please tell me how we save List of userdefined objects in XNA?
You're attempting to serialize private properties. That's not supported on Windows Phone 7. Which could easily be cause for the error.
Also, you have to ensure that all of the types you used for properties, is also serializeable, and that all types have a empty constructor.
Related
Summary:
I want a data annotation validator to reference another property in the same class (TitleAuthorAndPublishingConfiguration).
However, DB.SaveChanges() is not being called on this class directly. Rather it is being called on the parent of this class (WebsiteConfiguration).
Therefore validationContext.ObjectType is returning WebsiteConfiguration and I am unable to refer to properties of TitleAuthorAndPublishingConfiguration within the data annotation validator.
WebsiteConfiguration.cs
public class WebsiteConfiguration
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ID { get; set; }
public TitleAuthorAndPublishingConfiguration TitleAuthorAndPublishing { get; set; }
public BookChaptersAndSectionsConfiguration BookChaptersAndSections { get; set; }
public SocialMediaLoginsConfiguration SocialMediaLogins { get; set; }
public TagGroupsConfiguration TagGroups { get; set; }
}
public class TitleAuthorAndPublishingConfiguration
{
public string BookTitle { get; set; }
public bool IsPublished { get; set; }
// how do I access a property of current model when calling DB.SaveChanges() on parent?
[RequiredIfOtherFieldIsEnabled("IsPublished")]
public string Publisher { get; set; }
}
// ... and other sub models...
ApplicationDbContext.cs
DbSet<WebsiteConfiguration> WebsiteConfiguration {get;set;}
Example Update Code
public void SeedWebsiteConfiguration()
{
var titleAuthorAndPublishingConfiguration = new TitleAuthorAndPublishingConfiguration()
{
// seed values
};
var bookChaptersAndSectionsConfiguration = new BookChaptersAndSectionsConfiguration()
{
// seed values
};
var socialMediaLoginConfiguration = new SocialMediaLoginsConfiguration()
{
// seed values
};
var tagGroupsConfiguration = new TagGroupsConfiguration()
{
// seed values
};
var websiteConfiguration = new WebsiteConfiguration()
{
TitleAuthorAndPublishing = titleAuthorAndPublishingConfiguration,
BookChaptersAndSections = bookChaptersAndSectionsConfiguration,
SocialMediaLogins = socialMediaLoginConfiguration,
TagGroups = tagGroupsConfiguration
};
DB.WebsiteConfiguration.Add(websiteConfiguration);
DB.SaveChanges();
}
Validator Code
public class RequiredIfOtherFieldIsEnabledAttribute : ValidationAttribute
{
private string _ifWhatIsEnabled { get; set; }
public RequiredIfOtherFieldIsEnabledAttribute(string IfWhatIsEnabled)
{
_ifWhatIsEnabled = IfWhatIsEnabled;
}
protected override ValidationResult IsValid(object currentPropertyValue, ValidationContext validationContext)
{
var isEnabledProperty = validationContext.ObjectType.GetProperty(_ifWhatIsEnabled);
if (isEnabledProperty == null)
{
return new ValidationResult(
string.Format("Unknown property: {0}", _ifWhatIsEnabled)
);
}
var isEnabledPropertyValue = (bool)isEnabledProperty.GetValue(validationContext.ObjectInstance, null);
if (isEnabledPropertyValue == true)
{
if (String.IsNullOrEmpty(currentPropertyValue.ToString()))
{
return new ValidationResult(String.Format("This field is required if {0} is enabled", isEnabledProperty));
}
}
return ValidationResult.Success;
}
}
Questions
Is there a way for me to access child model properties from validationContext?
Am I misguided in my approach? Is there a better way to store multiple models as part of a larger model in a single DB table?
I was hoping not to have multiple config tables and calls to the DB. (There are 4 child models in this example, but there may be 10+ in the next app.)
The setup above meets my needs in so many ways. But I don't want to give up the functionality of DataAnnotations on the sub models!
Bonus Question
I have come across a few posts like this one:
How can I tell the Data Annotations validator to also validate complex child properties?
But that is 4 years old, and I'm wondering if anything has changed since then.
Am I trying to do something that is basically impossible (or at least very difficult)?
Am I trying to do something that is basically impossible (or at least
very difficult)?
No, there is a very simple solution that integrates perfectly with the framework and technologies using DataAnnotations.
You can create a custom ValidationAttribute that is called by EF Validation and call Validator.TryValidateObject inside. This way, when CustomValidation.IsValid is called by EF you launch child complex object validation by hand and so on for the whole object graph. As a bonus, you can gather all errors thanks to CompositeValidationResult.
i.e.
using System;
using System.ComponentModel.DataAnnotations;
using System.Collections.Generic;
public class Program
{
public static void Main() {
var person = new Person {
Address = new Address {
City = "SmallVille",
State = "TX",
Zip = new ZipCode()
},
Name = "Kent"
};
var context = new ValidationContext(person, null, null);
var results = new List<ValidationResult>();
Validator.TryValidateObject(person, context, results, true);
PrintResults(results, 0);
Console.ReadKey();
}
private static void PrintResults(IEnumerable<ValidationResult> results, Int32 indentationLevel) {
foreach (var validationResult in results) {
Console.WriteLine(validationResult.ErrorMessage);
Console.WriteLine();
if (validationResult is CompositeValidationResult) {
PrintResults(((CompositeValidationResult)validationResult).Results, indentationLevel + 1);
}
}
}
}
public class ValidateObjectAttribute: ValidationAttribute {
protected override ValidationResult IsValid(object value, ValidationContext validationContext) {
var results = new List<ValidationResult>();
var context = new ValidationContext(value, null, null);
Validator.TryValidateObject(value, context, results, true);
if (results.Count != 0) {
var compositeResults = new CompositeValidationResult(String.Format("Validation for {0} failed!", validationContext.DisplayName));
results.ForEach(compositeResults.AddResult);
return compositeResults;
}
return ValidationResult.Success;
}
}
public class CompositeValidationResult: ValidationResult {
private readonly List<ValidationResult> _results = new List<ValidationResult>();
public IEnumerable<ValidationResult> Results {
get {
return _results;
}
}
public CompositeValidationResult(string errorMessage) : base(errorMessage) {}
public CompositeValidationResult(string errorMessage, IEnumerable<string> memberNames) : base(errorMessage, memberNames) {}
protected CompositeValidationResult(ValidationResult validationResult) : base(validationResult) {}
public void AddResult(ValidationResult validationResult) {
_results.Add(validationResult);
}
}
public class Person {
[Required]
public String Name { get; set; }
[Required, ValidateObject]
public Address Address { get; set; }
}
public class Address {
[Required]
public String Street1 { get; set; }
public String Street2 { get; set; }
[Required]
public String City { get; set; }
[Required]
public String State { get; set; }
[Required, ValidateObject]
public ZipCode Zip { get; set; }
}
public class ZipCode {
[Required]
public String PrimaryCode { get; set; }
public String SubCode { get; set; }
}
I have a list of virtual folder structure. I need to bind that list to JsTreeView. The List may contain something like the below.
List of Items
Dh
Dh\Sub
Dh\Sub\Another
Dh1
Dh1\Sub1
Dh1\Sub1\Another1
Dh1\Sub1\Another2
Desired Output
Dh
|______ Sub
|_____Another
Dh1
|______ Sub1
|_____ Another1
|_____ Another2
As, I have tried logic using recursion. But, did not succeed with it. Can anybody tell me how can i achieve this. Any help to the problem will be highly appreciated.
Thanks
I am using the following class to serialize DB data to JSON and load into JS Tree View
/// <summary>
/// Model which represents data for js tree view
/// </summary>
public class JsTreeViewNode
{
private int int_id;
[JsonProperty(PropertyName = "id")]
public string Id { get; set; }
[JsonProperty(PropertyName = "text")]
public string Text { get; set; }
[JsonProperty(PropertyName = "children")]
public List<JsTreeViewNode> Children { get; set; }
[JsonProperty(PropertyName = "a_attr")]
public AnchorAttribute AAttributes { get; set; }
[JsonIgnore]
public int CurrentLevel { get; set; }
[JsonIgnore]
public int SortOrder { get; set; }
public JsTreeViewNode()
{
AAttributes = new AnchorAttribute();
}
public JsTreeViewNode(int id)
: this()
{
int_id = id;
this.Id = int_id.ToString();
AAttributes.Id = this.Id;
}
public int GetNodeId()
{
return int_id;
}
public JsTreeViewNode Clone()
{
var clone = (JsTreeViewNode)this.MemberwiseClone();
clone.Children = new List<JsTreeViewNode>();
clone.AAttributes = this.AAttributes.Clone();
return clone;
}
}
public class AnchorAttribute
{
[JsonProperty(PropertyName = "draggable")]
public string Draggable = "false";
[JsonProperty(PropertyName = "id")]
public string Id;
[JsonProperty(PropertyName = "class", NullValueHandling = NullValueHandling.Ignore)]
public string CssClassname;
public virtual AnchorAttribute Clone()
{
var clone = (AnchorAttribute)this.MemberwiseClone();
return clone;
}
}
Children property contains subnodes. Populating them depends on you app logic.
and later in controller
public virtual ContentResult LoadTreeData()
{
var treeData = Repository.GetTreeData();
return Content(JsonConvert.SerializeObject(treeData), "application/json");
}
Hope this helps
This is the first question I have asked, I'll try and keep this brief and detailed.
Basically, I am trying to create randomized cars made from a selection of models. I have 5 of each model part: Chassis, Engine, Spoiler and Wheels. The randomizer is working, models are loading. However, there is an issue where models are being drawn on other models. Usually there are only small parts of the model being drawn on other parts.
The models are being made in Maya(2013), Exported as .FBX and loaded into XNA. I follow this procedure for exporting: 1. Make Model.
2. Freeze transformation, center pivotpoint and delete history for each part of the model.
3. Combine the mesh and name appropriately.
Example to visualize this. Apparently I can't post images, so here is an Imgur link.
http://imgur.com/a/KHvPU#0
Thanks in advance for your help. This issue happens across more than just this example. I have 5 of each type (wheels, engines, chassis and spoilers), along with separate turbine instances for any models which have them, and other misc. parts. It seems to be totally random from one .FBX file to another... I cant work out if this is a Maya issue, or an XNA issue, or a combination of both :(
Relevant code. This is in a car Class, I have selected the relevant parts.
namespace CGD_RRR_Flipbook
{
//This is a class for the physics, position, color and perhaps race position (i.e. rank) of a car
public class Car : PhysicsObject
{
public string partName;
public int partNumber = 1; //(Initialised for wheel rotation requirements)
public List<string> partList = new List<string>();
//Animation Mesh and Bones Setup
//Chassis
public ModelBone chassis_01 { get; set; }
public ModelBone chassis_02 { get; set; }
public ModelBone chassis_03 { get; set; }
public ModelBone chassis_04 { get; set; }
public ModelBone chassis_05 { get; set; }
//Chassis Turbines
public ModelBone chassis_01_Turbine { get; set; }
public Matrix chassis_01_TurbineTransform { get; set; }
public ModelBone chassis_02_Turbine { get; set; }
public Matrix chassis_02_TurbineTransform { get; set; }
public ModelBone chassis_05_Turbine_Right { get; set; }
public Matrix chassis_05_Turbine_RightTransform { get; set; }
public ModelBone chassis_05_Turbine_Left { get; set; }
public Matrix chassis_05_Turbine_LeftTransform { get; set; }
//Engine
public ModelBone engine01 { get; set; }
public Matrix engine01Transform { get; set; }
public Matrix[] boneTransforms { get; set; }
//Movable Mesh and Bones setup
public int partPosition = 1; //Sets x-position amount
public float wheelRotationValueBase { get; set; }
public float wheelRotationValueUpdate { get; set; }
public float engineRotationValueBase { get; set; }
public float engineRotationValueUpdate { get; set; }
public Car(
ParticleSystem exhaustSmokeParticles,
ParticleSystem exhaustFlameParticles,
ParticleSystem exhaustBoostParticles,
ParticleSystem carDustParticles,
ParticleSystem sandstormParticles,
ParticleSystem explosionParticles,
HUDController _hudController, PlayerIndex _playerIndex, Terrain _terrain, GraphicsDevice _device, Effect _effect, Random randomNumber,
Controls keyBindings, int _player, SoundController _soundcontroller, string fileName = "", ContentManager content = null)
: base(fileName, content)
{
//Load Model
chassis_01_Turbine = model.Bones["Chassis_01_Turbine"];
chassis_01_TurbineTransform = chassis_01_Turbine.Transform;
chassis_02_Turbine = model.Bones["Chassis_02_Turbine"];
chassis_02_TurbineTransform = chassis_02_Turbine.Transform;
chassis_05_Turbine_Left = model.Bones["Chassis_05_Turbine_Left"];
chassis_05_Turbine_LeftTransform = chassis_05_Turbine_Left.Transform;
chassis_05_Turbine_Right = model.Bones["Chassis_05_Turbine_Right"];
chassis_05_Turbine_RightTransform = chassis_05_Turbine_Right.Transform;
chassis_01 = model.Bones["Chassis_01"];
chassis_02 = model.Bones["Chassis_02"];
chassis_03 = model.Bones["Chassis_03"];
chassis_04 = model.Bones["Chassis_04"];
chassis_05 = model.Bones["Chassis_05"];
engine01 = model.Bones["Engine_01"];
engine01Transform = engine01.Transform;
Update Function
public override void update(float dt)
{
//Calls randomiser (once) when player presses key in the generation state
if ((keyState.IsKeyDown(keyBinds.controlsList[player].forward)) && (!oldKeyState.IsKeyDown(keyBinds.controlsList[player].forward))
|| (padState.IsButtonDown(keyBinds.contForward)) && (!oldPadState.IsButtonDown(keyBinds.contForward)))
{
carRandomiser();
}
}
base.update(dt);
}
Draw Function.
public override void draw(Camera cam)
{
model.Root.Transform = worldMat; //sets model root transform to world
float wheelRotationValue = (wheelRotationValueBase + wheelRotationValueUpdate);
float engineRotationValue = (wheelRotationValueBase + wheelRotationValueUpdate);
//Chassis Engine Rotation Animation
Matrix engineRotation = Matrix.CreateRotationZ(engineRotationValue * 20);
chassis_01_Turbine.Transform = engineRotation * chassis_01_TurbineTransform;
chassis_02_Turbine.Transform = engineRotation * chassis_02_TurbineTransform;
chassis_05_Turbine_Left.Transform = engineRotation * chassis_05_Turbine_LeftTransform;
chassis_05_Turbine_Right.Transform = engineRotation * chassis_05_Turbine_RightTransform;
//Wheel Rotation Animation
//Matrix wheelRotation = Matrix.CreateRotationX(wheelRotationValue); //Create rotation Matrix
boneTransforms = new Matrix[model.Bones.Count]; //Creates array for holding modelBone transform matricies for use in draw method.
model.CopyAbsoluteBoneTransformsTo(boneTransforms); //Allocate trasform matricies
if (model != null)
{
foreach (ModelMesh mesh in model.Meshes)
{
//Draw parts assigned to car from partList.
foreach (string part in partList)
{
//Allows only the part in the list to be drawn, as opposed to all the possible parts.
if (mesh.Name == part)
{
effect.EnableDefaultLighting();
effect.PreferPerPixelLighting = true;
effect.World = boneTransforms[mesh.ParentBone.Index];// + worldMat;
effect.Projection = cam.projMat;
effect.View = cam.viewMat;
mesh.Draw();
}
}
}
}
}
}
The randomiser function.
//Car Randomiser Function. Looks for model bones allocated in FBX file.
public void carRandomiser()
{
//Delete contents of list.
partList.Clear();
//Spawn car engine
partNumber = rand.Next(0) + 1;
partName = ("Engine_0") + partNumber.ToString();
partList.Add(partName);
//Spawn car chassis
partNumber = rand.Next(5) + 1;
partName = ("Chassis_0") +partNumber.ToString();
partList.Add(partName);
//Spawn engine turbine for selected engine.
if (partName == ("Chassis_01"))
{
partList.Add("Chassis_01_Turbine");
}
if (partName == ("Chassis_02"))
{
partList.Add("Chassis_02_Turbine");
}
if (partName == ("Chassis_05"))
{
partList.Add("Chassis_05_Turbine_Left");
partList.Add("Chassis_05_Turbine_Right");
}
}
}
}
Does anyone know what the proper way of adding records using loops?
I have a system that handles Inventory, Currently I need to be able to Mass Create inventory as creating 50-100 identical items with different ID's would be tedious, What I did was create a MassCreate viewmodel that would essentially take a StartID and an EndID and a base Inventory Class and in the controller loop through the difference between those two ID's and create a record
The ViewModel isn't an issue and passes the data just fine:
public class MassCreateInventoryViewModel
{
public Inventory InventoryBase { get; set; }
public int StartID { get; set; }
public int EndID { get; set; }
public IEnumerable<SelectListItem> Products { get; set; }
}
I read somewhere that the db.SaveChanges() should be outside of the loop as it should only be called once:
for (int inventoryID = viewModel.StartID; inventoryID <= viewModel.EndID; inventoryID++)
{
Inventory newInventory = new Inventory
{
InventoryID = inventoryID,
ProductID = viewModel.InventoryBase.ProductID,
DateEdited = DateTime.Now,
EditedByUserID = WebSecurity.CurrentUserId,
CustomProperties = viewModel.InventoryBase.CustomProperties
};
Database.Inventories.Add(newInventory);
if (newInventory.CustomProperties != null && newInventory.CustomProperties.Any())
{
foreach (CustomDataType dt in newInventory.CustomProperties.Select(x => x.DataType).ToList())
{
Database.Entry(dt).State = EntityState.Unchanged;
}
}
}
Database.SaveChanges();
}
But when I try looping, it stores the first record just fine then throws a Collection was modified; enumeration operation may not execute. Exception. When I include the Database.SaveChanges() after the Add method, it throws A The property 'InventoryID' is part of the object's key information and cannot be modified. error.
The InventoryID is the Key in this table but has been set so that I can input my own ID.
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
[Display(Name = "Inventory ID")]
public new int InventoryID { get; set; }
The Custom Property is split into two models, the first being the base class.
public class CustomProperty
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int CustomPropertyID { get; set; }
public int CustomDataTypeID { get; set; }
[ForeignKey("CustomDataTypeID")]
public CustomDataType DataType { get; set; }
public string PropertyValue { get; set; }
}
and the second being the model thats mapped to the database:
[Table("CustomInventoryProperty")]
public class CustomInventoryProperty : CustomProperty
{
public int InventoryID { get; set; }
[ForeignKey("InventoryID")]
public virtual Inventory Inventory { get; set; }
}
Replace your for loop with this:
var dateEdited = DateTime.Now;
for (int inventoryID = viewModel.StartID; inventoryID <= viewModel.EndID; inventoryID++)
{
Inventory newInventory = new Inventory
{
InventoryID = inventoryID,
ProductID = viewModel.InventoryBase.ProductID,
DateEdited = dateEdited,
EditedByUserID = WebSecurity.CurrentUserId
};
if(viewModel.InventoryBase.CustomProperties != null)
{
newInventory.CustomProperties = new List<CustomProperties>();
foreach(var customProperty in viewModel.InventoryBase.CustomProperties)
{
newInventory.CustomProperties.Add(customProperty);
}
}
Database.Inventories.Add(newInventory);
Database.SaveChanges();
}
Below is a chunk of my ActionMethod. The part I'm struggling with is casting a new variable integers with all IntegerBufferValues from db.IntegerBuffers and then adding them to db.IntegerList.
var integers = new ICollection<Integers>();
const int COUNT = 1000000;
Stopwatch watch = Stopwatch.StartNew();
for (int c = 0; c < COUNT; c++)
{
integers = db.IntegerBuffers.OrderBy(i => i.IntegerBufferValue);
};
watch.Stop();
var integerList = new IntegerList
{
Direction = direction,
Performance = watch.ElapsedMilliseconds,
Integers = integers
};
db.IntegerLists.Add(integerList);
IntegerList
namespace Project.Models
{
public class IntegerList
{
public int IntegerListID { get; set; }
public string Direction { get; set; }
public long Performance { get; set; }
public virtual ICollection<Integer> Integers { get; set; }
}
}
IntegerBuffer
namespace Project.Models
{
public class IntegerBuffer
{
public int IntegerBufferID { get; set; }
public int IntegerBufferValue { get; set; }
}
}
Edit: To show Integer class.
Integer
namespace IntegerSorterApp.Models
{
public class Integer
{
public int IntegerID { get; set; }
public int IntegerValue { get; set; }
public int IntegerListID { get; set; }
public virtual IntegerList IntegerList { get; set; }
}
}
integers is currently a collection of IntegerBuffer objects. Use .Select to project them to just integers:
IEnumerable<int> integers;
// ...
integers = db.IntegerBuffers
.OrderBy(i => i.IntegerBufferValue)
.Select(i => i.IntegerBufferValue);
Or:
integers =
from buffer in db.IntegerBuffers
orderby buffer.IntegerBufferValue
select buffer.IntegerBufferValue;
Then, you assign to the collection, you could do something like this:
var integerList = new IntegerList
{
Direction = direction,
Performance = watch.ElapsedMilliseconds,
Integers = integers.ToList()
};
Update:
Oops, I didn't see that Integer is a class. My answer is to create a list of Int32 objects. The basics still apply: you'll need to use select to project to whatever structure you need. Now I don't understand your data model, but perhaps you want something like this:
// Create your list first so that the list ID is saved
var integerList = new IntegerList
{
Direction = direction,
Performance = watch.ElapsedMilliseconds,
};
db.IntegerLists.Add(integerList);
// Now create your Integer records with the ID of the list
foreach (var buffer in db.IntegerBuffers.OrderBy(b => b.IntegerBufferValue))
{
db.Integers.Add(new Integer
{
IntegerValue = buffer.IntegerBufferValue,
IntegerListID = integerList.IntegerListID
});
}
If this is a one-to-many relationship, which it appears to be, then setting IntegerListID on your Integer record will implicitly add it to the Integers collection of the list.