I've created a Xamarin.Forms UWP app and it felt to me like a bucket full of cement on your feet while trying to cross the mediterranean by swimming. So I switched to native UWP programming.
My application gets created to 95 % dynamically. All pages controls on the pages are dependend on what's saved in the database.
I have one login-page, a carouselPage (FlipView) and a QuitPage.
All other pages are dynamically loaded and added to the FlipView-ItemsSource.
In Xamarin I had a TemplateSelector like the one in this link:
https://github.com/alexrainman/CarouselView/blob/master/Demo/Views/MyTemplateSelector.cs
My question is:
How can I dynamically create DateTemplates out of my Views/Pages?
BTW:
I switched from Xamarin to native because there were heavy performance issues. The Carousel switches everytime to the first item and needed several seconds to show the "actual" page again, after the size was changed (through virtual keyboard).
I hope for a solution without such performance issues when there are more than 30 items in the list.
Maybe someone can explain why there is such a performance issue? I can't believe that every page is gonna be reloaded caused by the size changed by the virtual kb.
Thank you all in advance.
EDIT:
After I found the button for editing, here's what I got so far:
I have a Page named CarouselView. In the Xaml I have the FlipView named "myCarousel".
In the CodeBehind I have the following code:
public partial class WellcomeView : BasePage {
#region Fields + Properties
private int _position;
public int Position { get { return _position; } set { _position = value; } }
#endregion
public CarouselView() {
InitializeComponent();
myCarousel.ItemTemplateSelector = new MyTemplateSelector();
DataContext = new WellcomeViewModel(null, null, null, null, null);
}
public class MyTemplateSelector : Windows.UI.Xaml.Controls.DataTemplateSelector {
private DataTemplate GreetingTemplate;
...
public MyTemplateSelector() {
this.GreetingTemplate = (DataTemplate)Windows.UI.Xaml.Markup.XamlReader.Load(new GreetingView().Content.ToString());
...
// Here it throws an error. No matter if MainPage (with content) or other Views (with Content==null). But in every case I get a XamlParseException.
} // End Ctor
protected override DataTemplate SelectTemplateCore(object item, DependencyObject container) {
var TemplateType = item.GetType();
switch (TemplateType.Name) {
case "GreetingViewModel":
return base.SelectTemplateCore(GreetingTemplate );
default:
return base.SelectTemplateCore(BegruessungTemplate);
} // End switch-case
} // End SelectTemplateCore()
} // End MyTemplateSelector()
} // End class WellcomeView
Here's the Error I get...
And here's the StackTrace:
at Windows.UI.Xaml.Markup.XamlReader.Load(String xaml)
at MEDePORT_Win_Native.Views.WellcomeView.MyTemplateSelector..ctor()
at MEDePORT_Win_Native.Views.WellcomeView..ctor()
at MEDePORT_Win_Native.MEDePORT_Win_Native_XamlTypeInfo.XamlTypeInfoProvider.Activate_11_WellcomeView()
at MEDePORT_Win_Native.MEDePORT_Win_Native_XamlTypeInfo.XamlUserType.ActivateInstance()
at Windows.UI.Xaml.Controls.Frame.Navigate(Type sourcePageType, Object parameter)
at MEDePORT_Win_Native.App.OnLaunched(LaunchActivatedEventArgs e)
EDIT:
With "new MyView().Content.ToString()" I only get the name of the type. For example "Windows.Ui.Xaml.Controls.Grid".
So it seems like I need to extract xaml out of a view and convert it to a string.
EDIT EDIT EDIT EDIT EDIT:
What is the UWP equivalent for the following code?
DataTemplate template = new DataTemplate { DataType = typeof(< Type of the object the template refers>) };
Try to create your templates not as xaml-Files. Just copy the the Template-content to a xaml-DataTemplate in a new Resources.Xaml.
Then create Your TemplateSelector like this:
public class MyTemplateSelector : DataTemplateSelector {
public DataTemplate GreetingTemplate;
static ResourceDictionary dataTemplates;
public MyTemplateSelector() {
if (dataTemplates == null) {
dataTemplates = new Templates.DataTemplates();
}
GreetingTemplate = dataTemplates["GreetingTemplate"] as DataTemplate; // Look how to load Your Templates!
}
And return your templates like this:
protected override DataTemplate SelectTemplateCore(object item, DependencyObject container) {
var TemplateType = item.GetType();
switch (TemplateType.Name) {
case "GreetingViewModel":
return GreetingTemplate;
default:
return base.SelectTemplateCore(GreetingTemplate);
}
}
The Class Templates.DataTemplates() from the first code example looks like this:
public partial class DataTemplates : ResourceDictionary {
public DataTemplates() {
InitializeComponent();
}
}
and it's xaml contains your DataTemplates.
Hope, this helps.
Related
In my Unity3D Project I made a simple 2D Game and implemented a Data Manager to save and load Data. I created a List but get a NullReferenceException whenever I try to refer to it. I have a DataManager Class (saves & loads Data) and a UserData Class (stores the fields that are needed to be saved or loaded). In the User Data Class I declare in initialize a List of integer type. The List contains the unlocked Levels and it is initialized in the Constructor of the User Data Class.
This is the DataManager Class:
public static class DataManager
{
public static List<int> GetUnlockedLevels()
{
UserData userData = Load();
return userData.unlockedLevels; // This method returns nothing, not even null!
}
private static void Save(UserData data)
{
string path = GetDataFilePath();
BinaryFormatter binaryFormatter = new BinaryFormatter();
using (FileStream fileStream = File.Open(path, FileMode.OpenOrCreate))
{
binaryFormatter.Serialize(fileStream, data);
}
}
private static UserData Load()
{
string path = GetDataFilePath();
if (!File.Exists(path))
{
UserData userData = new UserData();
Save(userData);
}
BinaryFormatter binaryFormatter = new BinaryFormatter();
using (FileStream fileStream = File.Open(path, FileMode.Open))
{
return (UserData)binaryFormatter.Deserialize(fileStream);
}
}
And here comes the UserData Class:
[Serializable]
public class UserData
{
public int score;
public List<int> unlockedLevels;
public UserData()
{
score = 50;
unlockedLevels = new List<int>();
unlockedLevels.Add(1); //unlocked by default
unlockedLevels.Add(2); //unlocked by default
unlockedLevels.Add(3); //unlocked by default
}
}
The problem is: the first method of the DataManager "GetUnlockedLevels()" returns nothing.
The weird part: I have the exact same Data Manager in another project where it works properly. In that other project, the GetUnlockedLevels-method returns "System.Collections.Generic.List´1[System.Int32]" when I return it via "Debug.Log". But in the new project, the method returns literally nothing (not even null; the exception comes at a later point)
I am sure that I didn't make a copy-paste-mistake. What could be the root for this error?
What IDE are you using? I ask because the answer to your question is that you have a typo in your UserData constructor. Normally you would be alerted to this as soon as you built within your IDE as it would fail to compile.
[Serializable]
public class UserData
{
public int score;
public List<int> unlockedlevels; // This line
public UserData()
{
score = 50;
unlockedLevels = new List<int>(); // And this line
unlockedLevels.Add(1); // And this line
unlockedLevels.Add(2); // And this line
unlockedLevels.Add(3); // And this line
}
}
unlockedLevels
vs
unlockedlevels
Solution: the file was created but was empty. I manually deleted the saved file and from then it worked properly.
Currently i am using JpaItemWriter to write the list of objects as below which is working fine.
Now i want to change the JpaItemWriter to JdbcBatchItemWriter due to performance issue.
public class MyItemWriter implements ItemWriter<List<MyDomainObject>> {
#Override
public void write(List<? extends Lists<MyDomainObject>> items) {
JpaItemWriter<MyDomainObject> writer = new JpaItemWriter<>();
for(List<MyDomainObject> o : items)
{
writer.write(o);
}
}
}
Suggest a sample snippets which uses the JdbcBatchItemWriter to write the List of objects will helps. Tried using the ItemSqlParameterSourceProvider it did't help ending up in org.springframework.dao.InvalidDataAccessApiUsageException: No value supplied for the SQL parameter exception
You example is not correct. You are creating a JpaItemWriter in the write method, so a new instance is created on each call to write. This is probably the cause of your performance issue.
More importantly, lifecycle methods of the delegate writer (open/update/close) will not be honored (it is not the case for JpaItemWriter which does not implement ItemStream but this would be a problem if the delegate is an item stream). Your MyItemWriter implementation should be something like:
public class MyItemWriter implements ItemWriter<List<MyDomainObject>> {
private JpaItemWriter jpaItemWriter;
public MyItemWriter(JpaItemWriter jpaItemWriter) {
this. jpaItemWriter = jpaItemWriter;
}
#Override
public void write(List<? extends Lists<MyDomainObject>> items) {
for(List<MyDomainObject> o : items) {
this. jpaItemWriter.write(o);
}
}
}
Now if you want to use the JdbcBatchItemWriter to write a list of lists, see Spring Batch - Using an ItemWriter with List of Lists.
Edit: Added a sample code of how to set the delegate as requested in comments:
#Bean
public ListUnpackingItemWriter<T> itemWriter() {
JdbcBatchItemWriter<T> jdbcBatchItemWriter = null; // configure your jdbcBatchItemWriter
ListUnpackingItemWriter<T> listUnpackingItemWriter = new ListUnpackingItemWriter<>();
listUnpackingItemWriter.setDelegate(jdbcBatchItemWriter);
return listUnpackingItemWriter;
}
I am working on a very simple program, looking like this:
public class WicketApplication extends WebApplication implements Comparable<Object>{
private List<Person> persons = Arrays.asList(
new Person("Mikkel", "20-02-91", 60169803),
new Person("Jonas", "02-04-90", 86946512),
new Person("Steffen", "15-07-90", 12684358),
new Person("Rasmus", "08-12-93", 13842652),
new Person("Michael", "10-10-65", 97642851));
/**
* #see org.apache.wicket.Application#getHomePage()
*/
#Override
public Class<? extends WebPage> getHomePage() {
return SimpleView.class;
}
public static WicketApplication get() {
return (WicketApplication) Application.get();
}
/**
* #return #see org.apache.wicket.Application#init()
*/
public List<Person> getPersons() {
return persons;
}
public List<Person> getSortedList(){
return Collections.sort(persons);
//This won't work before implementing comparator i know, but how??
}
#Override
public void init() {
super.init();
// add your configuration here
}
#Override
public int compareTo(Object o) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
}
That was the class where i just put my people into a list.
public class SimpleView extends SimpleViewPage {
public SimpleView() {
ListView persons = new ListView("persons", getPersons()) {
#Override
protected void populateItem(ListItem item) {
Person person = (Person) item.getModelObject();
item.add(new Label("name", person.getName()));
item.add(new Label("birthdate", person.getBirthdate()));
item.add(new Label("phone", person.getPhone()));
}
};
add(persons);
add(new Label("size", "Number of people " + getPersons().size()));
}
}
And here is what i do with the people.
Basicly i want the program to show a table with all the data(this already works).
Now i want to be able to sort them. But i can't for the life of me figure it out. I'm still rather new at programming, and i want to have a button below my table that can sort on name, bday or phone number. Was thinking about trying to Comparable, but can't remember it that well, and not sure how it works with Wicket..
Thanks for the help in advance :)
What you need is the DataView component, which provides all the support you need for sorting (and paging, should you require it later on).
Here's a working example, if you click on the "Source Code" link in the top right corner, you can see that most of the things you want from a sortable table work out of the box. All you need is to create a suitable data provider.
If you use DataView with a SortableDataProvider, you don't need to worry about writing your own dynamic Comparator. (Which is not a terribly hard task itself, but it's easy to get it wrong.)
I wrote the following customization and have it applied as part of a composite on most of my tests. My entities have a read-only Id, but I'm using their SetId method in this customization to make sure all entities have some Id if they are transient (don't have an Id already).
public class SetEntityIdCustomization : ICustomization {
public void Customize(IFixture fixture) {
var engine = ((Fixture)fixture).Engine;
fixture.Customizations.Add(new Postprocessor(
engine, o => {
var entity = o as BaseEntity;
if (entity == null || !entity.IsTransient()) {
return;
}
entity.SetId(fixture.CreateAnonymous<Guid>());
}));
}
}
This has been working great, until I discovered a very odd thing today. If I feed a test one of my entities that directly inherits from BaseEntity, all is well and it's writeable properties are auto-filled. However, if I ask for an entity that inherits from something further down from BaseEntity, my customization prevents the properties from auto-filling.
The User entity in this test method is filled properly:
public class User : BaseEntity {
public string Email { get; set; }
public int CoolThings { get; set; }
}
...
[Theory, AutoDomainData]
public void SomeTest(User user, ...) {
// user.Email and user.CoolThings have auto-filled values, as expected.
...
}
However, the AwesomeUser entity in the following test does not get any of the same properties auto-filled.
public class AwesomeUser : User {
...
}
...
[Theory, AutoDomainData]
public void SomeOtherTest(AwesomeUser user, ...) {
// user.Email nor user.CoolThings have auto-filled values. What gives?
...
}
In both test cases, the Id property is auto-filled because of my customization. If I remove my customization, the SomeOtherTest's AwesomeUser instance gets its inherited properties auto-filled just fine. I must assume that my customization is what is messing things up.
Is there a better way to get all my BaseEntity instances to set their Id, or is there something else I'm missing with AutoFixture? I've applied my customization first, in the middle, and last, to no avail.
The solution provided above is a pretty clever attempt, but not something I've seen before. A more idiomatic solution would be something like this:
public void Customize(IFixture fixture)
{
fixture.Customizations.Add(
new FilteringSpecimenBuilder(
new Postprocessor(
new BaseEntityBuilder(
new ConstructorInvoker(
new ModestConstructorQuery())),
new AutoPropertiesCommand().Execute),
new BaseEntitySpecification()));
}
private class BaseEntityBuilder : ISpecimenBuilder
{
private readonly ISpecimenBuilder builder;
private readonly IRequestSpecification specification;
public BaseEntityBuilder(ISpecimenBuilder builder)
{
this.builder = builder;
this.specification = new BaseEntitySpecification();
}
public object Create(object request, ISpecimenContext context)
{
if (!this.specification.IsSatisfiedBy(request))
return new NoSpecimen(request);
var b = (BaseEntity)this.builder.Create(request, context);
b.SetId((Guid)context.Resolve(typeof(Guid)));
return b;
}
}
private class BaseEntitySpecification : IRequestSpecification
{
public bool IsSatisfiedBy(object request)
{
var t = request as Type;
if (t == null)
return false;
if (!typeof(BaseEntity).IsAssignableFrom(t))
return false;
return true;
}
}
As you can see, this isn't a simple one-liner, which is indicative of AutoFixture being a rather opinionated library. In this case, AutoFixture's opinion is:
Favor object composition over class inheritance.
-Design Patterns, p. 20
AutoFixture is first and foremost a TDD tool, and one of the main advantages of TDD is that it provides feedback about class design. In this case, the feedback is: Inheritance is awkward and troublesome. Reconsider the design.
In wicket without saving to the session how can i have a persistent object for example a list which can be set in one panel and accessed from another. Iv done a lot of googleing and im not entirely sure how this would work. Any help would be appreciated greatly! Thank you.
Related to the comments above, I will try and explain what I was thinking.
Disclaimer: It's been more than a year since I worked with Wicket, so the following should be read as an overall proof-of-concept. I cannot guarantee that it will compile (actually, I can almost certainly guarantee that it will not.)
public class MyPage extends ... {
...
MyPageModel pm = new MyPageModel();
add(new MyPanel1(pm));
add(new MyPanel2(pm));
...
}
public class MyPageModel implements Serializable {
private IModel<List<MyDataObject>> dataObjects;
public MyPageModel() {
this.dataObjects = // Load list from somewhere
}
public IModel<List<MyDataObject>> getDataObjects() {
return this.dataObjects;
}
}
public class MyPanel1 extends ... {
private MyPageModel pageModel;
public MyPanel1(MyPageModel pageModel) {
this.pageModel = pageModel;
...
add(new ListSomethingComponent<MyDataObject>(pageModel.getDataObjects)); // Some list renderer component which takes a IModel<List<MyDataObject>> as data
}
}
public class MyPanel2 extends ... {
private MyPageModel pageModel;
public MyPanel2(MyPageModel pageModel) {
// Same as MyPanel1...
}
}