Can anyone help me to solve this problem?
I am using visual studio2010 and its windows phone 7 application
I have created addpet.xaml and mypet.xaml.
Created IsolatedStorageSetting object in mypet.cs file
{
public static IsolatedStorageSettings settings=IsolatedStorageSettings.ApplicationSettings;
}
I have 5 textboxes and I am storing its value in list item.That list stores in IsolatedStorageSetting object.
{
SaveMypet savepet = new SaveMypet();
savepet.Name = txt_name.ToString();
savepet.Birthday = txt_birthday.ToString();
savepet.FavFood = txt_favouritefood.ToString();
savepet.DocNo = txt_doctorsno.ToString();
savepet.VacDate = txt_vacdate.ToString();
savepet.FavToy = txt_favouritetoy.ToString();
// savepet.Image1 = image1.Source;
listMyPet.Add(savepet);
settings.Add("iso_listMyPet", listMyPet);
}
Now I want to access this object in addpet.cs and cast it to list and then want to assign to listbox.
Like this, I have did but does not work
Created list object in addpet.cs
{
static List<pg_addPet> list_listMyPet = null;
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
list_listMyPet = (List<pg_addPet>)pg_addPet.settings["iso_mypet_list"];
listbox_mypet.ItemsSource = list_listMyPet;
}
And my SaveMypet class is
public class SaveMypet
{
public string Name { get; set; }
public string Birthday { get; set; }
public string FavFood { get; set; }
public string DocNo { get; set; }
public string VacDate { get; set; }
public string FavToy { get; set; }
// public ImageSource Image1 { get; set; }
}
You've declared the settings property as static. Therefore, you need to use the class name to access it:
list_listMyPet = (List<pg_addPet>)pg_mypet.settings["iso_mypet_list"];
Try the following:
if(!pg_mypet.settings.TryGetValue("iso_mypet_list", out list_listMyPet))
{
list_listMyPet = new List<pg_addPet>();
}
This will try to retrieve the value and if if fails it will create an empty list instead.
Related
I found this great post by Chris Sainty: Creating Bespoke Input Components for Blazor from Scratch. It is exactly what I need, but not with string, but with uploaded files IBrowserFile. So I have adapted and extended the example for me. The customized component displays the new files and saves it in my model, but in the CSS the status unfortunately stays on class="modified invalid".
I must be missing a small detail here. What is it? Thanks in advance for any hints.
Here is my code reduced to the essentials.
Selection.razor
#page "/selection"
#inherits ParentComponent<SelectionTestModel>
<PageComponent #ref="Page" Model="Model" StatusCode="StatusCode" PageType="PageType.Touch">
<PageBody>
<EditForm Model="Model" OnValidSubmit="Save">
<DataAnnotationsValidator />
<DocumentComponent #ref="DocumentUpload" #bind-Documents="Model.Files" />
</EditForm>
</PageBody>
</PageComponent>
#code {
private DocumentComponent DocumentUpload;
}
SelectionTestModel.cs
public class SelectionTestModel
{
public int? KeyID { get; set; }
/* ... */
[System.ComponentModel.DisplayName("Document")]
[System.ComponentModel.DataAnnotations.Display(Name = "Document")]
[System.ComponentModel.DataAnnotations.Range(2, 2, ErrorMessage = "You have to bring exactly two files!")]
public List<DocumentModel> Files { get; set; } = new List<DocumentModel>();
}
DocumentModel
public class DocumentModel
{
public int? Id { get; set; }
public string Reference { get; set; }
public string Name { get; set; }
public long Size { get; set; }
public string ContentType { get; set; }
public string Content { get; set; } /*file as base64 string*/
}
DocumentComponent.razor
#using System.Linq.Expressions
<div class="dropzone rounded #_dropClass #_validClass">
<InputFile id="inputDrop" multiple
ondragover="event.preventDefault()"
ondragstart="event.dataTransfer.setData('', event.target.id)"
accept="#AllowedFileTypes"
OnChange="OnInputFileChange"
#ondragenter="HandleDragEnter"
#ondragleave="HandleDragLeave" />
#*...*#
</div>
#code {
[CascadingParameter] public EditContext EditContext { get; set; }
[Parameter] public List<DocumentModel> Documents { get; set; } = new List<DocumentModel>();
[Parameter] public EventCallback<List<DocumentModel>> DocumentsChanged { get; set; }
[Parameter] public Expression<Func<List<DocumentModel>>> DocumentsExpression { get; set; }
/*...*/
public List<string> AllowedFileTypes { get; set; } = new List<string> { ".pdf", /*...*/ };
private FieldIdentifier _fieldIdentifier;
private string _validClass => EditContext?.FieldCssClass(_fieldIdentifier) ?? null;
protected override void OnInitialized()
{
base.OnInitialized();
_fieldIdentifier = FieldIdentifier.Create(DocumentsExpression);
}
private async Task OnInputFileChange(InputFileChangeEventArgs e)
{
// validation: do we accept the file (content type, amount of files, size)
if (e.FileCount == 1) // keep it simple for this example
{
// read from IBrowserFile and return DocumentModel in memory only
Documents.Add(await SaveFile(e.File));
await DocumentsChanged.InvokeAsync(Documents);
EditContext?.NotifyFieldChanged(_fieldIdentifier);
}
}
/*...*/
}
How does it behave in the browser (Chrome)
After loading the page everything looks as expected.
After that I upload a single file. So I have one file and I expect two. The validation turns red and I get "modified invalid". So far everything is great.
Finally I drag another file into the component and get two files. I can also see this in the model. But unfortunately the class attribute "modified valid" is not set.
Thanks again for any advice
I dug too deep in the wrong direction and didn't see the obvious.
The problem is that there is an attribute set in the model that does not throw an error, but also cannot validate.
The Range attribute is not for lists and therefore the model could never validate. With an own attribute I could work around this.
SelectionTestModel.cs
[Library.Validation.Attribute.ListRange(2, 2)]
public List<DocumentModel> Files { get; set; } = new List<DocumentModel>();
ListRangeAttribute.cs
namespace Library.Validation.Attribute
{
public class ListRangeAttribute : ValidationAttribute
{
public int Minimum { get; set; }
public int Maximum { get; set; }
public ListRangeAttribute(int minimum = 0, int maximum = int.MaxValue)
{
Minimum = minimum > 0 ? minimum : 0;
Maximum = maximum;
}
public string GetErrorMessage(string displayName) { /* ... */ }
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var list = value as IList;
if (list == null)
{
throw new InvalidOperationException($"Attribute {nameof(ListRangeAttribute)} must be on a property of type {nameof(IList)}.");
}
if ((list?.Count ?? 0) < Minimum || (list?.Count ?? int.MaxValue) > Maximum)
{
return new ValidationResult(GetErrorMessage(validationContext.DisplayName), new[] { validationContext.MemberName });
}
return ValidationResult.Success;
}
}
}
I hope this post can help others.
Remaining: Now I am left with a new mystery.
Why does the validation text disappear after a save button click, which could not be saved due to an invalid state of the model!?
I'm leveraging the Project functionality in Automapper and Entity Framework, but I'm running into an issue where Automapper doesn't seem to want to project one enum type to another.
I have the following entities:
public class UserProfile
{
public Guid Id { get; set; }
public string Name { get; set; }
private HashSet<UserProfilePhone> m_Phones;
public virtual HashSet<UserProfilePhone> Phones
{
get { return m_Phones ?? (m_Phones = new HashSet<UserProfilePhone>()); }
set { this.m_Phones = value; }
}
}
public class UserProfilePhone
{
public PhoneType Type { get; set; }
public virtual string Number { get; set; }
}
public enum PhoneType
{
Home = 1,
Work = 2,
Mobile = 3,
Other = 4
}
I then am projecting these types to the following models:
public class UserProfileModel
{
public Guid Id { get; set; }
public virtual string Name { get; set; }
public IEnumerable<UserProfilePhoneModel> Phones { get; set; }
}
public class UserProfilePhoneModel
{
public UserProfilePhoneTypeModel Type { get; set; }
public string Number { get; set; }
}
public enum UserProfilePhoneTypeModel
{
Home = 1,
Work = 2,
Mobile = 3,
Other = 4
}
I then setup my mappings like so:
Mapper.CreateMap<PhoneType, UserProfilePhoneTypeModel>();
Mapper.CreateMap<UserProfilePhone, UserProfilePhoneModel>();
Mapper.CreateMap<UserProfile, UserProfileModel>();
And finally I'm executing my projection:
var result = dbContext.UserProfiles.Project().To<UserProfileModel>();
When I do this, I get the following exception:
AutoMapper.AutoMapperMappingException: Unable to create a map expression from MyNamespace.PhoneType to
MyNamespace.Models.UserProfilePhoneTypeModel
Unable to create a map expression from MyNamespace.PhoneType to MyNamespace.Models.UserProfilePhoneTypeModel
Result StackTrace:
at System.Collections.Concurrent.ConcurrentDictionary2.GetOrAdd(TKey
key, Func2 valueFactory)
...
I've tried creating explicit mappings, but they appear to be ignored. What am I doing wrong here?
As usual, I figured out the answer almost as soon as I posted the question.
Modifying the create map line to provide an explicit cast did the trick:
Mapper.CreateMap<UserProfilePhone, UserProfilePhoneModel>()
.ForMember(m => m.Type, opt => opt.MapFrom(t => (UserProfilePhoneTypeModel)t.Type));
Hi everybody and thanks in advance for solution
I've these objects
List<AccessModuleInfo> listOfAccessModuleInfo = new List<AccessModuleInfo>();
public class AccessModuleInfo
{
public int AccessModuleId { get; set; }
public string AccessModuleName { get; set; }
public List<AccessRoleInfo> ListOfAccessRole { get; set; }
}
public class AccessRoleInfo
{
public int AccessRoleId { get; set; }
public string AccessRoleName { get; set; }
public bool AccessRoleValue { get; set; }
}
I receive listOfAccessModuleInfo that is already fill and when I try to update AccessRoleValue in specific AccessModuleInfo, all AccessRoleValue with the same AccessRoleId are updated .
I want update only AccessRoleValue of specific AccessModuleInfo (for example with AccessModuleId = 4)
Thanks
Normally something like this should work just fine:
// You didn't confuse == vs = did you?
// Single also helps us debug and ensure we're only getting one result
var itemToUpdate = listOfAccessModuleInfo.Where(x => x.AccessModuleId == 4).Single();
itemToUpdate.ListOfAccessRole.ForEach(x => x.AccessRoleValue = newValue);
By injecting values into my domain object, I would keep the values of some properties.
Example:
Domain model
public class Person
{
public string Name { get; set; }
public Guid ID { get; set; }
public DateTime CreateAt { get; set; }
public string Notes { get; set; }
public IList<string> Tags { get; set; }
}
View Model
public class PersonViewMode
{
public string Name { get; set; }
public Guid ID { get; set; }
public DateTime CreateAt { get; set; }
public string Notes { get; set; }
public IList<string> Tags { get; set; }
public PersonViewMode() { ID = Guid.NewGuid(); } //You should use this value when it is the Target
}
Sample
var p = new Person
{
ID = Guid.NewGuid() //Should be ignored!
,
Name = "Riderman"
,
CreateAt = DateTime.Now
,
Notes = "teste de nota"
,
Tags = new[] {"Tag1", "Tag2", "Tag3"}
};
var pvm = new PersonViewMode();
pvm.InjectFrom(p); //Should use the ID value generated in the class constructor PersonViewMode
if you delete the set; from from the ViewModel's ID then it won't be set;
otherwise you could save the value of ID in a separate variable and put it back after injecting,
or you can create a custom valueinjection that would ignore "ID" or would receive a list of properties to ignore as a parameter
here's the example for a custom injection that receives a list of property names to ignore:
public class MyInj : ConventionInjection
{
private readonly string[] ignores = new string[] { };
public MyInj(params string[] ignores)
{
this.ignores = ignores;
}
protected override bool Match(ConventionInfo c)
{
if (ignores.Contains(c.SourceProp.Name)) return false;
return c.SourceProp.Name == c.TargetProp.Name && c.SourceProp.Type == c.TargetProp.Type;
}
}
and use it like this:
pvm.InjectFrom(new MyInj("ID"), p);
if you need to ignore more, you can do like this:
pvm.InjectFrom(new MyInj("ID","Prop2","Prop3"), p);
I have the following code...
internal sealed class Menu_Metadata
{
private Menu_Metadata() { }
[Key]
public int MenuHeaderID { get; set; }
public string MenuHeaderName { get; set; }
[Include]
[Association("MenuHeader_MenuItem", "MenuHeaderID", "MenuHeaderID")]
public IEnumerable<MenuItem> MenuItems { get; set; }
}
public class EmployeeMenuItem
{
[Key]
public int MenuItemID { get; set; }
public int MenuHeaderID { get; set; }
public string MenuItemName { get; set; }
}
[MetadataType(typeof(Menu_Metadata))]
public class EmployeeMenu
{
public int MenuHeaderID { get; set; }
public string MenuHeaderName { get; set; }
public IEnumerable<EmployeeMenuItem> MenuItems { get; set; }
}
[EnableClientAccess()]
public class EmployeeMenuService : DomainService
{
public IQueryable<EmployeeMenu> GetEmployeeMenu()
{
BusinessLogic.Employee blEmployee = new BusinessLogic.Employee();
int employeeId = blEmployee.GetEmployeeIdFromUserName(HttpContext.Current.User.Identity.Name);
var menuHeaders = blEmployee.GetEmployeeMenuHeaders(employeeId);
// This works here!
IQueryable<EmployeeMenu> retValue = from mh in menuHeaders
select new EmployeeMenu
{
MenuHeaderID = mh.ID,
MenuHeaderName = mh.HeaderName,
MenuItems = from mhi in mh.MenuHeaderItems
select new EmployeeMenuItem
{
MenuItemID = mhi.MenuItemID,
MenuHeaderID = mhi.MenuHeaderID,
MenuItemName = mhi.MenuItem.MenuItemName
}
};
return retValue;
}
}
which is consumed by a Silverlight Accordion control
EmployeeMenuContext employeeMenuContext = new EmployeeMenuContext();
accordion2.ItemsSource = employeeMenuContext.EmployeeMenus;
employeeMenuContext.Load(employeeMenuContext.GetEmployeeMenuQuery());
The MenuHeaderName's are coming through just fine, and the MenuItems is populated for the 1st MenuHeader, but the other 3 MenuItems are empty.
Any ideas why?
At what point is it easier to use EF4 and RIA??? This seems so incredibly and needlessly complex to get a simple Entity with a sub-class in it!
I'm not entirely sure, but it appears that the problem may have been that I was trying to databind in the xaml constructor. I created a Loaded event and moved the code there and it seems to work now.