Search Unity

NData - MVVM framework for NGUI

Discussion in 'Assets and Asset Store' started by Art Of Bytes, Mar 15, 2012.

  1. Art Of Bytes

    Art Of Bytes

    Joined:
    Jun 8, 2011
    Posts:
    198
    Hm, that's a very interesting use-case.
    One possible option (not the best one, though) is to have something like:
    Code (csharp):
    1.  
    2. class Skill;
    3.  
    4. class Person
    5. {
    6.  Collection<Skill> Skills;
    7. }
    8.  
    9. class Root
    10. {
    11.  Collection<Person> People;
    12. }
    13.  
    and bind first droplist to "People" and the second one to "People.SelectedItem.Skills" then when switching person, second droplist will update its content altogether with item selection. Drawbacks are: duplication of skills container in all people and skills droplist repopulation on person selection change.

    Another solution could be to create a two-directional binding for SelectdIndex, so that you could bind Skills.SelectedIndex to People.SelectedItem.SkillIndex. But that has nothing to do with view so binding is an overkill, because on a viewModel level it would be enough to leave everything like you have it now and do something like:
    Code (csharp):
    1.  
    2. class Context
    3. {
    4.   public Context()
    5.   {
    6.     People.OnSelectionChanged += () => { Skills.SelectItem(People.SelectedItem.SkillIndex; };
    7.   }
    8. }
    9.  
    Unless skills list is unique for every person, then the very first solution can make sense. Anyways, it's up to you, use the solution that seems more appropriate to you. Good luck.
     
  2. Nezabyte

    Nezabyte

    Joined:
    Aug 21, 2012
    Posts:
    110
    Thanks for the ideas! Got it working fine with something similar to the 2nd code snippet.
     
  3. Nezabyte

    Nezabyte

    Joined:
    Aug 21, 2012
    Posts:
    110
    I'm trying to use a switch on a string variable and ran into this error: "Can not convert from System.Reflection.TargetInvocationException to System.String". Should I be doing this differently?

    People is a EzData collection with a EzData SkillToTrain variable property (of type Skill, an EzData context) and EzData sub-property Name string.

    Code (csharp):
    1.  
    2. foreach(Person x in People.Items) {
    3.     switch (x.SkillToTrain.Name) {
    4.     case "Skill1":
    5.         x.Skill1++; break;
    6.     case "Skill2":
    7.         x.Skill2++; break;
    8.     }
    9. }
    10.  
     
  4. Art Of Bytes

    Art Of Bytes

    Joined:
    Jun 8, 2011
    Posts:
    198

    Everything should be fine, except the case when SkillToTrain is null in one of the people. Then, however, it should fire NullRefenceException, not the TargetInvocationException. Could you post how SkillToTrain is declared? Because our test setup ( View attachment $TestContext.cs ) created from your description, works as expected.
     
  5. Nezabyte

    Nezabyte

    Joined:
    Aug 21, 2012
    Posts:
    110
    You're probably already aware of this, but just in case, ever since the latest version of unity (4.2), these warnings of obsolete calls show up in the console:

    $ndataobsolete.PNG
     
  6. Nezabyte

    Nezabyte

    Joined:
    Aug 21, 2012
    Posts:
    110
    Is it possible to use enum for bindings? I didn't see enum on the reference list, so I wasn't sure if it's unsupported, or if I could do some conversion between enum and int to use with ndata.
     
  7. Art Of Bytes

    Art Of Bytes

    Joined:
    Jun 8, 2011
    Posts:
    198
    We tried binding to enums, but knowing the possible issues with "reflection vs. iOS", we ended up using regular int properties, with a cast to enum for usage on ViewModel level, like this:

    Code (csharp):
    1.  
    2.         public enum GameState : int
    3.     {
    4.         LoginScreen = 0,
    5.         Menu = 1,
    6.         Settings = 2,
    7.         Achievements = 3,
    8.                 ...
    9.        }
    10.  
    11.                 #region Property GameState
    12.         private readonly EZData.Property<int> _privateGameStateProperty = new EZData.Property<int>();
    13.         public EZData.Property<int> GameStateProperty { get { return _privateGameStateProperty; } }
    14.         public GameState GameState
    15.         {
    16.         get    { return (GameState)GameStateProperty.GetValue();    }
    17.         set    { GameStateProperty.SetValue((int)value); }
    18.         }
    19.         #endregion
    20.  
    Regarding warnings - in many cases we can't just switch to the newer Unity4-only solution, because many people are still using unity 3.5.7. However, all the warnings that can be fixed without breaking the compatibility with Unity3, will be fixed with the next update.
     
  8. tripknotix

    tripknotix

    Joined:
    Apr 21, 2011
    Posts:
    744
    It turns out the issue is that I had 2 ViewModel's in my scene, one for audio, and one for some data used elsewhere. Does anyone know how to fix this issue with having more than 1 viewmodel in your scene?
     
  9. Nezabyte

    Nezabyte

    Joined:
    Aug 21, 2012
    Posts:
    110
    Would it be possible to use pre-processor directives to check the unity version? I've heard of devs using that to include different code based on what the user was running.
     
  10. schragnasher

    schragnasher

    Joined:
    Oct 7, 2012
    Posts:
    117
    Ok after some more testing here is the issue im having with scene loading. I have a persistent context and different scenes which reference it. When changing scenes i get a null reference exception to a binding which it says was destroyed. I seems to be updating bindings in the middle of loading a new scene or something. Example Linked


    https://docs.google.com/file/d/0B9fQ42r9nUlOZTZOLThHaEo0SHc/edit?usp=sharing

    load latest ngui and ndata to make it work. Didnt want to pass around the libraries. I feel like i could change my architecture and get around it, but i thought id see what you think/
     
    Last edited: Jul 31, 2013
  11. concave

    concave

    Joined:
    Aug 28, 2012
    Posts:
    49
    hi! got a little beginners question. i bound an UITable to an Collection. I created a Template. On this Template there is a OnClickBinding.
    What works is that the item gets selected on click but the onclickbinding event never fired. If i have the onclick binding on a separate button outside of the table - the event is triggert and everthing works like i want - but i need the buttons inside the table to trigger the event. what am i doing wrong?
     
  12. concave

    concave

    Joined:
    Aug 28, 2012
    Posts:
    49
    if i should not use a command binding like OnClickBinding - can you give me an example where and how i should "subscribe" to the selecteditemchanged event.
     
  13. concave

    concave

    Joined:
    Aug 28, 2012
    Posts:
    49
    i want to bind my menu (no popup list) to a collection. when an item is selected - i want to call a method on the businesslogic side. how does it work if i use data binding only ? where do i subscribe to the OnSelectedItemChanged on the LogicSide? How can i do that (just adding to delegate or what?) - please give me a code snipped!
     
  14. Art Of Bytes

    Art Of Bytes

    Joined:
    Jun 8, 2011
    Posts:
    198
    In this case exception occurs, because your data context persists through scenes, so when some UI elements bind to properties, their references are stored to be able to notify them about changes. That's why first context update after scene change tries to call a binding update on destroyed object. There's a possible hot-fix in attachment, it handles the exception, and just ignores and removes destroyed objects from bound bindings list.
     

    Attached Files:

  15. Art Of Bytes

    Art Of Bytes

    Joined:
    Jun 8, 2011
    Posts:
    198
    Hi, in this case you can add the button with onclickbinding as a child object in your item template. In this case, you'll have two box colliders, first - in the template root object, that will affect selection, and the second is the collider in the button object, that will trigger onclickbinding. Note that when binding inside of an item template, all paths are referring to the item, not the parent context, so if you bind to DoSmth function in your command binding, you must have a corresponding public void DoSmth() in your item class.

    it could be done in the class where your collection is defined, like this:
    Code (csharp):
    1.  
    2.         public class MyContext
    3.     {
    4.         #region Collection MyCollection
    5.         private readonly EZData.Collection<MyItem> _privateMyCollection = new EZData.Collection<MyItem>(false);
    6.         public EZData.Collection<MyItem> MyCollection { get { return _privateMyCollection; } }
    7.         #endregion
    8.        
    9.         private void MySelectionChangeHandler()
    10.         {
    11.         }
    12.        
    13.         public MyContext()
    14.         {
    15.             MyCollection.OnSelectionChange += MySelectionChangeHandler;
    16.         }
    17.     }
    18.  
    But here's more interesting question - "how does it work if i use data binding only ?'

    Sometimes you'll need to take some action when data changes, or user interacts with UI. That's why events in properties and collections exist, and that's why there are command bindings. However, in some typical cases, you can avoid handling data change manually. For example, if in your case, you need to get notified about selection change to update some other field in UI to, say, SomeValue from newly selected item. Then you could bind this field that requires update straight to MyCollection.SelectedItem.SomeValue and it will be updated automatically. That's not necessarily your case, if you need to do some complex action, or call some service, or anything more than just UI updates, then of-course collection OnSelectionChange event - is what you need.
     
  16. schragnasher

    schragnasher

    Joined:
    Oct 7, 2012
    Posts:
    117
    Was the behavior intended? If so i would prefer to setup my code to avoid the exception. I believe i can rework the setup to keep the data persistent but avoid th exception. Perhaps i could seperate the data from the contexts and only keep the data persistent.
     
  17. concave

    concave

    Joined:
    Aug 28, 2012
    Posts:
    49


    Thanks for the response! The "delegating" works great!!!

    youre right the call is more complex -> controller -> dao -> db - but this part works now!

    but I have a further problem:

    1. i want to update the content of my uitable through the bound collection - that works pretty well - but everytime the update is executet when the complete panel is invisble (due swichting between views) - the table positing is complete destroyed after visibilty is reseted. do you have a clue why that happens?

    2. i need a table of tables or some better way to drag/swipe through 3x3 Elements (dragable panel) colums. when i use table of tables the positioning is not working right - gets reset after update - maybe thats not an ndata problem only but if there is an solution i would appreciate any help with this problem.
     
  18. concave

    concave

    Joined:
    Aug 28, 2012
    Posts:
    49
    i got another problem:

    * i have a UITable bound to a collection - the UITable contains a certain amount of my "TableItemTemplate" witch consist of a foreground button and a backround checkbox and a collider on the parent of the Template.

    * Now if i select one template it opens a new view using visibility binding - in this view i have a button if i click the button i do some stuff and i want to make the "foreground button" of the selected TableItem invisible.

    * Unfortunalty that visibility binding to the BoolValue of the selected Table Item isn't recognized somehow. I have a debug log in the GetterSetter of the property and it is reset properly but the binding doesn't work.

    * i directly bound the TableTemplate foreground button to: MyContext.Table.SelectedItem.BoolValue the value is reseted in the Busnesslogic after Click of the overlaying View button - but the TableTemplates foregroundbutton isn't made invisible. (ok there might be anouther mistake it might effect all tableitems but that isn't working too - i have a debuglog in the bool binding apply new value method a it wasn't called)

    what am i doing wrong? i though about your descriptions in your last answer but somehow i can't get it to work. can you help me?
     
    Last edited: Aug 2, 2013
  19. realblues

    realblues

    Joined:
    Dec 10, 2010
    Posts:
    10
    Hmm I Finally found this thread

    There looks lot of knowledges, I'm curious why it doesn't have own forum.
     
  20. Art Of Bytes

    Art Of Bytes

    Joined:
    Jun 8, 2011
    Posts:
    198
    Well, it is quite a valid use-case. We're including the provided hot-fix to the next versions of NData, so you can safely use the context across the scenes and there's no need to avoid the setup you have now. Especially since the workaround you mentioned could possibly lead to data duplication and some redundant operations.
     
  21. Art Of Bytes

    Art Of Bytes

    Joined:
    Jun 8, 2011
    Posts:
    198
    1 - we're checking that, table contents update is still a huge area for improvement.
    2 - for that you might take a look at NGUI UIGrid, it may suit better than UITable in this case
     
  22. Art Of Bytes

    Art Of Bytes

    Joined:
    Jun 8, 2011
    Posts:
    198
    If you have doubts in correctness of you binding paths, first of all you should check them with the "Tools -> NData -> Validate Bindings" command from main menu while having your UI root game object selected. Also your issue seems to be something not so trivial, so reproducing it from description may show result different from yours. If you could provide a test scene exported to package or just zipped - it would be much more clear.
     
  23. schragnasher

    schragnasher

    Joined:
    Oct 7, 2012
    Posts:
    117
    I think i found a bug with this. I have a panel with some player statistics which i am using on multiple scenes. I think this new code is destroying the bindings for the new scene because this panel is effectively the same for each scene but is unloaded in the old scene and loaded again in the new scene. Does that make sense?
     
  24. Nezabyte

    Nezabyte

    Joined:
    Aug 21, 2012
    Posts:
    110
    Could you provide an example of NguiOnDropBinding? Sounds like something I could make use of to make the inventory system more interesting - drag and drop items into slots.
     
  25. aikitect

    aikitect

    Joined:
    Dec 28, 2012
    Posts:
    28
    EDIT: Nevermind, this has been resolved. I had an extra PlayerHomeController in my object hierarchy.

    I am trying the MonoBehaviourContext, but am running into a NullReferenceException that I can't seem to figure out. When I click on a button that calls ToggleMoreMenu() in PlayerHomeController (see code below), I get a NullReferenceException telling me that Model is null. However, I am 100% sure it is set correctly in the Unity Editor, and when I put a Debug.Log() in the Awake function, it actually logs to the console twice. The first time, it shows the PlayerHomeLogic component correctly. The second time, it shows null (which explains why I get the NullReferenceException later). Why is this happening, and how can I fix this?

    PlayerHomeController.cs
    Code (csharp):
    1.  
    2. using UnityEngine;
    3.  
    4. public class PlayerHomeController : EZData.MonoBehaviourContext
    5. {
    6.     #region Initialization
    7.  
    8.     public NguiRootContext View;
    9.     public PlayerHomeLogic Model;
    10.  
    11.     private void Awake()
    12.     {
    13.         View.SetContext(this);
    14.     }
    15.  
    16.     #endregion
    17.  
    18.     #region Properties
    19.  
    20.     private readonly EZData.Property<bool> _privateMoreMenuStateProperty = new EZData.Property<bool>();
    21.     public EZData.Property<bool> MoreMenuStateProperty { get { return _privateMoreMenuStateProperty; } }
    22.     public bool MoreMenuState
    23.     {
    24.         get { return MoreMenuStateProperty.GetValue(); }
    25.         set { MoreMenuStateProperty.SetValue(value); }
    26.     }
    27.  
    28.     #endregion
    29.  
    30.     #region Commands
    31.  
    32.     public void ToggleMoreMenu()
    33.     {
    34.         MoreMenuState = !MoreMenuState;
    35.         Model.ToggleMoreMenu(MoreMenuState);
    36.     }
    37.  
    38.     #endregion
    39. }
    40.  
    PlayerHomeLogic.cs
    Code (csharp):
    1. using UnityEngine;
    2.  
    3. public class PlayerHomeLogic : MonoBehaviour
    4. {
    5.     #region Properties
    6.  
    7.     public PlayerHomeController Controller;
    8.     public GameObject MoreMenu;
    9.  
    10.     #endregion
    11.  
    12.     #region Public Methods
    13.  
    14.     public void ToggleMoreMenu(bool toOpen)
    15.     {
    16.         if (toOpen)
    17.         {
    18.             Debug.Log("Opening!");
    19.             TweenPosition.Begin(
    20.                 MoreMenu,
    21.                 0.25f,
    22.                 new Vector3(103.0f, -228.0f, 0.0f)
    23.             );
    24.         }
    25.         else
    26.         {
    27.             Debug.Log("Closing!");
    28.             TweenPosition.Begin(
    29.                 MoreMenu,
    30.                 0.25f,
    31.                 new Vector3(103.0f, 270.0f, 0.0f)
    32.             );
    33.         }
    34.     }
    35.  
    36.     #endregion
    37. }
    38.  
     
    Last edited: Aug 12, 2013
  26. concave

    concave

    Joined:
    Aug 28, 2012
    Posts:
    49
    thanks for reply - i was in the hospital last week so i had no time to prepare a example. i will do it after this really urgent task.

    i very urgently need to get the sprite binding to work - is there a complete example. i got it to work with uitexture
     
  27. Art Of Bytes

    Art Of Bytes

    Joined:
    Jun 8, 2011
    Posts:
    198
    Sprite binding is rather simple, here you go an example scene: View attachment $SpriteBindingExample.unitypackage , as you can see if you have a sprite component and sprite binding next to it with path to the string property, sprite will change to whatever you set in this property. Of-course, within the atlas specified in sprite component.

    Drag'n'Drop example is on the way.
     
  28. Art Of Bytes

    Art Of Bytes

    Joined:
    Jun 8, 2011
    Posts:
    198
    Sorry for late reply. Here's an idea, you seem to have some common UI elements with the common ViewModel (that already has "don't destroy on load"), you could have a portion of your UI that is persistent throughout scenes marked with "don't destroy on load" too. Then it won't be re-created causing less troubles.
     
  29. concave

    concave

    Joined:
    Aug 28, 2012
    Posts:
    49
    hi art of bytes team - unfortunatly been to hospital last week - so i couldn't prepare an example of my last problem... (will be up next)

    but i have a new very urgent problem with UISprite binding...

    i have items in a list with icon witch i want to bind to an uisprite
    i made a property for the item prepared a collection (source binding)
    validated the binding path everthing should work just fine but it doesn't the sprites aren't shown...

    can you provide us with an simple working example/tutorial of the sprite binding (on an item in a collection) so a can check with my solution...

    thx
     
  30. Art Of Bytes

    Art Of Bytes

    Joined:
    Jun 8, 2011
    Posts:
    198
    hi, you must have missed the message, dedicated sprite binding example is here: View attachment 63643 . Also, in ItemsList example, items' icons in the table are implemented with UISprite + SpriteBinding.
     
  31. concave

    concave

    Joined:
    Aug 28, 2012
    Posts:
    49
    hey BIG THANKS - i really missed that MSG!!! - got it to work a few hours ago anyhow - was confused by the type of the _UiSpriteReceiver member... didn't take a closer look so i bound UISprite instead of UIAtlas.Sprite... now it works... stupid mistake... have some problems when switching between views though - z position of Sprite holding GO gets reseted - maybe another Bug somewhere... will check it soon.

    Did you allready think about an Algorithm/"Mechanic" to load "really huge" lists (about 5000 items consisting of a view sprites labels) without performance problems?
    I have to find a solution for this task - i have only 50 items in my list and the performance isn't accepatble (scrolling is not going smooth anymore)
    - now i ask myself if there is a solution allready? otherwise i would think about one and come back with some first thoughts.
     
  32. Art Of Bytes

    Art Of Bytes

    Joined:
    Jun 8, 2011
    Posts:
    198
    We've approached this "huge data" problem couple of times, so far no clean and nice solution was found. In any case it won't be a UITable + ItemsSourceBinding, but most likely some alternative table control with binding to collection embedded to it, with very non-trivial logic.

    Could you describe a task you need it for? is this table content of highly dynamical nature, or it's initialized once and there's only need for fast browsing around it? Is it initialized all at once or items are added in time. Are they added to the end of the list only, or into the middle of the list too? Should you be able to scroll to any position in the list immediately, or it's supposed to be getting content as you scroll it (similar to twitter or facebook feeds)?

    This information can help us to understand what exactly is required or what tradeoffs can be offered to developers to make it more or less universal, but still fast.
     
  33. concave

    concave

    Joined:
    Aug 28, 2012
    Posts:
    49
    Could you describe a task you need it for?
    -1. i have a View where i List all items of currently selected "packages". a package consistst of 200items with rich data content (sprite,text,audio).
    - 2. i have another list of images so i will need a solution for UITexture too as it is not recommened by NGUI developer to put huge textures in an
    own atlas.(makes no sense)

    is this table content of highly dynamical nature, or it's initialized once and there's only need for fast browsing around it?
    - it should be dynamically loaded from db/filesystem into memory (collection) when needed.
    now it is loaded from db/filesystem all at once when another package is selected.

    Is it initialized all at once or items are added in time. Are they added to the end of the list only, or into the middle of the list too?
    - acertain amount of items can be added in time.
    - The items should be inserted in alphabetical order. (u are able to reorder it if localization changes)

    Should you be able to scroll to any position in the list immediately,
    or it's supposed to be getting content as you scroll it (similar to twitter or facebook feeds)?
    hmm - i think thats a matter of feasibility - the better solution would be the immediately one
    but its maybe easier to show some loading sprite for items witch get into the focus (scroll index)

    and the collection will have different "item" types as i need a GUIElement that indicates the beginning of
    a new alphabetical category.

    ---
    I thougth maybe you can load it "on demand" maybe something like n-5 / n+5 next items and then like fb feeds dynamically...
    and destroy more far away ones.(bestcase - according to the available memory)

    - to the richcontent collection you have one , with synchronized index (offset), that takes care of the order by loading
    all of the currently selected item ids/names. maybe it would be useful if this collection uses an own type that capsules
    - name of item, - is selected, - is in focus, - is loading ...

    how would a immedaitely solution look like?
     
  34. concave

    concave

    Joined:
    Aug 28, 2012
    Posts:
    49
    hey thanks for fast reply!

    Could you describe a task you need it for?
    -1. i have a View where i List all items of currently selected "packages". a package consistst of 200items with rich data content (sprite,text,audio).
    - 2. i have another list of images so i will need a solution for UITexture too as it is not recommened by NGUI developer to put huge textures in an
    own atlas.(makes no sense)

    is this table content of highly dynamical nature, or it's initialized once and there's only need for fast browsing around it?
    - it should be dynamically loaded from db/filesystem into memory (collection) when needed.
    now it is loaded from db/filesystem all at once when another package is selected.

    Is it initialized all at once or items are added in time. Are they added to the end of the list only, or into the middle of the list too?
    - acertain amount of items can be added in time.
    - The items should be inserted in alphabetical order. (u are able to reorder it if localization changes)

    Should you be able to scroll to any position in the list immediately,
    or it's supposed to be getting content as you scroll it (similar to twitter or facebook feeds)?
    hmm - i think thats a matter of feasibility - the better solution would be the immediately one
    but its maybe easier to show some loading sprite for items witch get into the focus (scroll index)

    and the collection will have different "item" types as i need a GUIElement that indicates the beginning of
    a new alphabetical category.

    ---
    I thougth maybe you can load it "on demand" maybe something like n-5 / n+5 next items and then like fb feeds dynamically...
    and destroy more far away ones.(bestcase - according to the available memory)

    - to the richcontent collection you have one , with synchronized index (offset), that takes care of the order by loading
    all of the currently selected item ids/names. maybe it would be useful if this collection uses an own type that capsules
    - name of item, - is selected, - is in focus, - is loading ...

    how would a immedaitely solution look like?
     
  35. scritchy

    scritchy

    Joined:
    Dec 30, 2010
    Posts:
    94
    Hi. So, i may have missed this being addressed on another page of this thread, if so i'm very sorry, but i couldn't find mention of it.

    When building in unity 4.2 against Windows Store App target, the "Use net core" build option (which is analogous for what is needed to pass WACK test, more or less) throws these errors in ndata. Presumably because in net core for windows 8 apps, these c# methods or extensions are moved or removed. Can you please advise on how to proceed?


    Assets\NData\NGUI\NData\Core\Property.cs(27,25): error CS1061: 'System.Type' does not contain a definition for 'IsValueType' and no extension method 'IsValueType' accepting a first argument of type 'System.Type' could be found (are you missing a using directive or an assembly reference?)

    Assets\NData\NGUI\NData\Core\Context.cs(160,53): error CS1061: 'System.Type' does not contain a definition for 'GetMethod' and no extension method 'GetMethod' accepting a first argument of type 'System.Type' could be found (are you missing a using directive or an assembly reference?)

    Assets\NData\NGUI\NData\Core\Context.cs(167,29): error CS0117: 'System.Delegate' does not contain a definition for 'CreateDelegate'

    Assets\NData\NGUI\NData\Core\Context.cs(175,53): error CS1061: 'System.Type' does not contain a definition for 'GetProperty' and no extension method 'GetProperty' accepting a first argument of type 'System.Type' could be found (are you missing a using directive or an assembly reference?)

    Assets\NData\NGUI\NData\Core\Context.cs(181,49): error CS1061: 'System.Type' does not contain a definition for 'GetProperty' and no extension method 'GetProperty' accepting a first argument of type 'System.Type' could be found (are you missing a using directive or an assembly reference?)

    Assets\NData\NGUI\NData\Core\Context.cs(201,53): error CS1061: 'System.Type' does not contain a definition for 'GetProperty' and no extension method 'GetProperty' accepting a first argument of type 'System.Type' could be found (are you missing a using directive or an assembly reference?)

    Assets\NData\NGUI\NData\Core\Context.cs(239,68): error CS1061: 'System.Type' does not contain a definition for 'GetProperty' and no extension method 'GetProperty' accepting a first argument of type 'System.Type' could be found (are you missing a using directive or an assembly reference?)

    Assets\NData\NGUI\NData\Core\Context.cs(244,56): error CS1061: 'System.Type' does not contain a definition for 'GetField' and no extension method 'GetField' accepting a first argument of type 'System.Type' could be found (are you missing a using directive or an assembly reference?)

    Assets\NData\NGUI\NData\Core\Context.cs(251,72): error CS1061: 'System.Type' does not contain a definition for 'GetProperty' and no extension method 'GetProperty' accepting a first argument of type 'System.Type' could be found (are you missing a using directive or an assembly reference?)

    Assets\NData\NGUI\NData\Core\Context.cs(257,53): error CS1061: 'System.Type' does not contain a definition for 'GetProperty' and no extension method 'GetProperty' accepting a first argument of type 'System.Type' could be found (are you missing a using directive or an assembly reference?)

    Assets\NData\NGUI\NData\Core\Context.cs(289,57): error CS1061: 'System.Type' does not contain a definition for 'GetProperty' and no extension method 'GetProperty' accepting a first argument of type 'System.Type' could be found (are you missing a using directive or an assembly reference?)

    Assets\NData\NGUI\NData\Core\Context.cs(295,50): error CS1061: 'System.Type' does not contain a definition for 'GetProperty' and no extension method 'GetProperty' accepting a first argument of type 'System.Type' could be found (are you missing a using directive or an assembly reference?)

    Assets\NData\NGUI\NData\Core\Context.cs(325,68): error CS1061: 'System.Type' does not contain a definition for 'GetProperty' and no extension method 'GetProperty' accepting a first argument of type 'System.Type' could be found (are you missing a using directive or an assembly reference?)

    Assets\NData\NGUI\NData\Core\Context.cs(330,56): error CS1061: 'System.Type' does not contain a definition for 'GetField' and no extension method 'GetField' accepting a first argument of type 'System.Type' could be found (are you missing a using directive or an assembly reference?)

    Assets\NData\NGUI\NData\Core\Context.cs(337,72): error CS1061: 'System.Type' does not contain a definition for 'GetProperty' and no extension method 'GetProperty' accepting a first argument of type 'System.Type' could be found (are you missing a using directive or an assembly reference?)

    Assets\NData\NGUI\NData\Core\Context.cs(343,57): error CS1061: 'System.Type' does not contain a definition for 'GetProperty' and no extension method 'GetProperty' accepting a first argument of type 'System.Type' could be found (are you missing a using directive or an assembly reference?)

    Assets\NData\NGUI\NData\NguiAudibleBinding.cs(4,9): warning CS0436: The type 'System.SerializableAttribute' in 'g:\temp\Predefines.cs' conflicts with the imported type 'System.SerializableAttribute' in 'h:\UglyCastle\Library\ScriptAssemblies\Assembly-CSharp-firstpass.dll'. Using the type defined in 'g:\temp\Predefines.cs'.
     
  36. Nezabyte

    Nezabyte

    Joined:
    Aug 21, 2012
    Posts:
    110
    Couple questions -

    1) Have you thought about adding a OnTooltip() binding? To show data about an item in the pop-up box, it needs to know about the item's information (specifically a string variable). I'm not sure how to go about doing this since OnTooltip() needs to be on a Monobehavior script. I thought about retrieving the info from the NGuiTextBinding component, but it doesn't seem to expose the string it is bound to.

    Also, OnTooltip() would be on inventory slots using NGuiItemDataContext. The slots may or may not contain an actual inventory item, so OnTooltip() would only display if an item was in the slot.

    2) Can you achieve polymorphic behavior with bindings? I have various classes deriving from Item since, for example, only weapon items would have MinDamage and MaxDamage properties. In the example below, I want to return the character item slot that a weapon can go into. However, I can't cast EzData.VariableContext<WeaponItem> to EzData.VariableContext<Item>.

    My backup plan would be to use enums to handle the different types of Items, but that means a shield item could have Min and Max damage values, which is not ideal.

    Code (csharp):
    1.  
    2.     private EZData.VariableContext<Item> GetHardpoint (Item item)
    3.     {
    4.         if (item is WeaponItem)
    5.             return RightWeaponEzVariableContext;
    6.         else if (item is ShieldItem)
    7.             return ShieldItemEzVariableContext;
    8.         else
    9.             return null;
    10.     }
    11.  
     
    Last edited: Aug 17, 2013
  37. concave

    concave

    Joined:
    Aug 28, 2012
    Posts:
    49
    i found a similar implementation of my idea descrbed above for a not completly but a little bit similar "plattform" ... i will try to make a prototype for ngui/ndata in the next few days.
     
  38. jaybennett

    jaybennett

    Joined:
    Jul 10, 2012
    Posts:
    165
    Hey AOB! I just got NGUI and NData a couple days ago. I'm new with MVVM, so could you walk me through setting up an example?

    Lets say for example I have a simple player data class:

    Code (csharp):
    1.  
    2. public class PlayerData
    3. {
    4.     public string PlayerName;
    5.     public string PlayerID;
    6.    
    7.     // stats
    8.     public int StrengthXp;
    9.     public int StrengthXpToLevel;
    10.     public int StrengthLvl;
    11.  
    12.     public PlayerData(...)
    13.     {
    14.         // init the fields from DB data
    15.     }
    16. }
    17.  
    Lets say my application loads one of these PlayerData objects as the local player data after a login. How do I bind this with the Context object? I mean that's really my first step, right?
     
    Last edited: Aug 19, 2013
  39. Art Of Bytes

    Art Of Bytes

    Joined:
    Jun 8, 2011
    Posts:
    198
    Hi, you most likely can't do much about it. We need to workaround this missing reflection-based functionality in the core classes. We're working on this, it's a priority task.
     
  40. Art Of Bytes

    Art Of Bytes

    Joined:
    Jun 8, 2011
    Posts:
    198
    you can use something like this:
    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. [System.Serializable]
    6. [AddComponentMenu("NGUI/NData/Tooltip Binding")]
    7. public class NguiTooltipBinding : NguiTextBinding
    8. {
    9.     private string _tooltipText;
    10.    
    11.     void OnTooltip (bool show)
    12.     {
    13.         if (!show)
    14.         {
    15.             UITooltip.ShowText(null);
    16.             return;
    17.         }
    18.        
    19.         if (string.IsNullOrEmpty(_tooltipText))
    20.             return;
    21.        
    22.         UITooltip.ShowText(_tooltipText);
    23.     }
    24.    
    25.     protected override void ApplyNewValue (string newValue)
    26.     {
    27.         _tooltipText = newValue;
    28.     }
    29. }
    30.  
    you can avoid inappropriate values in your plan B by the following hierarchy, however, we'll see if it's possible to make VariableContext more flexible in this aspect you highlighted:
    Code (csharp):
    1.  
    2. enum ItemType
    3. {
    4. Generic = 0,
    5. Shield = 1,
    6. Weapon = 2,
    7. }
    8.  
    9. class Item
    10. {
    11. public virtual ItemType Type { get { return ItemType.Generic; } }
    12. public string Name { get; set; }
    13. }
    14.  
    15. class Shield : Item
    16. {
    17. public override ItemType Type { get { return ItemType.Shield; } }
    18. public int DamageResist { get; set; }
    19. }
    20.  
    21. class Weapon : Item
    22. {
    23. public override ItemType Type { get { return ItemType.Weapon; } }
    24. public int MinDamage { get; set; }
    25. public int MaxDamage { get; set; }
    26. }
    27.  
    You can bind to Type property in your UI and show corresponding UI depending on the item type.
    Another option is to make your own custom binding that binds to object and then then does some specific stuff based on what it can be cast to.
     
  41. Art Of Bytes

    Art Of Bytes

    Joined:
    Jun 8, 2011
    Posts:
    198
    Your example implies that you have certain view (UI) with fields that display PlayerName, StrengthXP, etc. In a typical use-case you have a ViewModel (also referred to as a root context here and there). This context is either inherited from EZData.Context or EZData.MonoBehaviourContext. And contains the data in the way most appropriate for your UI.

    In your case your root context will most likely contain an instance of a PlayerContext class that will be constructed from PlayerData and initialize its properties from PlayerData fields. This PlayerContext will be similar to Character class from ItemsList example scene, but with your own defined properties. Here's some hint how it can look like:

    Code (csharp):
    1.  
    2. public class PlayerContext : EZData.Context
    3. {
    4.     #region Property Name
    5.     private readonly EZData.Property<string> _privateNameProperty = new EZData.Property<string>();
    6.     public EZData.Property<string> NameProperty { get { return _privateNameProperty; } }
    7.     public string Name
    8.     {
    9.     get    { return NameProperty.GetValue();    }
    10.     set    { NameProperty.SetValue(value); }
    11.     }
    12.     #endregion
    13.  
    14.     #region Property StrengthXp
    15.     private readonly EZData.Property<int> _privateStrengthXpProperty = new EZData.Property<int>();
    16.     public EZData.Property<int> StrengthXpProperty { get { return _privateStrengthXpProperty; } }
    17.     public int StrengthXp
    18.     {
    19.     get    { return StrengthXpProperty.GetValue();    }
    20.     set    { StrengthXpProperty.SetValue(value); }
    21.     }
    22.     #endregion
    23.  
    24.     //...
    25.    
    26.     public PlayerContext(PlayerData data)
    27.     {
    28.         Name = data.PlayerName;
    29.         StrengthXp = data.StrengthXp;
    30.         // ...
    31.     }
    32. }
    33.  
    34. public class RootContext : EZData.MonoBehaviourContext
    35. {
    36.     #region Player
    37.     public readonly EZData.VariableContext<PlayerContext> PlayerEzVariableContext = new EZData.VariableContext<PlayerContext>(null);
    38.     public PlayerContext Player
    39.     {
    40.         get { return PlayerEzVariableContext.Value; }
    41.         set { PlayerEzVariableContext.Value = value; }
    42.     }
    43.     #endregion
    44.    
    45.     void Start()
    46.     {
    47.         // LogIn and load player data
    48.     }      
    49.    
    50.     void OnPlayerDataLoaded(PlayerData data)
    51.     {
    52.         Player = new PlayerContext(data);
    53.     }
    54. }
    55.  
    Then your binding paths in UI will look like: Player.Name or Player.StrengthXp, and so on.
     
    Last edited: Aug 20, 2013
  42. concave

    concave

    Joined:
    Aug 28, 2012
    Posts:
    49
    hi!
    @short question inbetween - i have a solution but iam unsure if it is the most efficient.
    can you give me a simple and small example binding script on how to change a value from View->Model for example a boolean.

    @"huge" collection: i started but its not really trivial... will take me some more time. r there any news from your side?

    kind regards
     
  43. Art Of Bytes

    Art Of Bytes

    Joined:
    Jun 8, 2011
    Posts:
    198
    Simplest binding would be a class inherited from NguiBinding with Bind and Unbind functions override, like this:

    Code (csharp):
    1.  
    2. public class SimpleBinding : NguiBinding
    3. {
    4.     private EZData.Property<bool> _property;
    5.    
    6.     protected override void Unbind()
    7.     {
    8.         base.Unbind();
    9.        
    10.         if (_property != null)
    11.         {
    12.             _property.OnChange -= ModelToView;
    13.             _property = null;
    14.         }
    15.     }
    16.    
    17.     protected override void Bind()
    18.     {
    19.         base.Bind();
    20.        
    21.         var context = GetContext(Path);
    22.         if (context != null)
    23.         {
    24.             _property = context.FindProperty<bool>(Path, this);
    25.             if (_property != null)
    26.                 _property.OnChange += ModelToView;
    27.         }
    28.     }
    29.    
    30.     private bool _ignoreChange;
    31.     protected override void ModelToView()
    32.     {
    33.         base.OnChange();
    34.         if (_ignoreChange)
    35.             return;
    36.    
    37.         // Apply _property.Value to view
    38.     }
    39.    
    40.     public void ViewToModel(bool newValue) // Called by view to set property value
    41.     {
    42.         if (_property == null)
    43.             return;
    44.        
    45.         _ignoreChange = true;
    46.         _property.SetValue(newValue);
    47.         _ignoreChange = false;
    48.     }
    49. }
    50.  
    Regarding huge data issue, nothing new, right now we'll be busy with Windows Store platform support.
     
  44. Nezabyte

    Nezabyte

    Joined:
    Aug 21, 2012
    Posts:
    110
    PlayerContext doesn't need to derive from EzData.Context ?
     
  45. scritchy

    scritchy

    Joined:
    Dec 30, 2010
    Posts:
    94
    Doh. OK well i have some time still. When do you think it will be? i always forget to check back to this thread, and i don't get email notifications from this forum...

    thanks

     
  46. Art Of Bytes

    Art Of Bytes

    Joined:
    Jun 8, 2011
    Posts:
    198
    It should, thanks :)
     
  47. Nezabyte

    Nezabyte

    Joined:
    Aug 21, 2012
    Posts:
    110
    Thanks! Will give it a shot.

    By the way, any plans for a support forum? sadly we can't search the thread for old questions/answers and instead have to navigate page by page.
     
  48. Nezabyte

    Nezabyte

    Joined:
    Aug 21, 2012
    Posts:
    110
    Could you elaborate on this? Is there a certain process to creating a custom binding, and specifically to an object? Or do you mean binding to properties of an object?
     
  49. jaybennett

    jaybennett

    Joined:
    Jul 10, 2012
    Posts:
    165
    So am I correct that this PlayerContext object should be the run time place to store the data? I'm sort of new to the pattern.. should I ditch the PlayerData completely after load and just work with the PlayerContext?

    And basically the root context is the start of the entire data layer?

    Very cool :)
     
    Last edited: Aug 23, 2013
  50. Art Of Bytes

    Art Of Bytes

    Joined:
    Jun 8, 2011
    Posts:
    198
    The whole binding would look like this, instead of setting label text you can interpret weapon and armor instances as you wish. However this whole approach is not absolutely correct architecturally, because as you can see, binding (view layer) uses classes in ItemsListContexts namespace (viewmodel layer), what it is not supposed to do.

    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. [System.Serializable]
    6. public class ItemTypeBinding : NguiBinding
    7. {
    8.     private EZData.Property<ItemsListContexts.Item> _property;
    9.    
    10.     private UILabel _label;
    11.     public override void Awake()
    12.     {
    13.         base.Awake();  
    14.         _label = gameObject.GetComponent<UILabel>();
    15.     }
    16.    
    17.     protected override void Unbind()
    18.     {
    19.         base.Unbind();
    20.        
    21.         if (_property != null)
    22.         {
    23.             _property.OnChange -= OnChange;
    24.             _property = null;
    25.         }
    26.     }
    27.    
    28.     protected override void Bind()
    29.     {
    30.         base.Bind();
    31.        
    32.         var context = GetContext(Path);
    33.         if (context != null)
    34.         {
    35.             _property = context.FindProperty<ItemsListContexts.Item>(Path, this);
    36.             if (_property != null)
    37.                 _property.OnChange += OnChange;
    38.         }
    39.     }
    40.    
    41.     protected override void OnChange()
    42.     {
    43.         base.OnChange();
    44.        
    45.         if (_label == null)
    46.             return;
    47.  
    48.         var weapon = _property.GetValue() as ItemsListContexts.WeaponItem;
    49.         var armor = _property.GetValue() as ItemsListContexts.ArmorItem;
    50.  
    51.         if (weapon != null)
    52.             _label.text = "Weapon";
    53.         else if (armor != null)
    54.             _label.text = "Armor";
    55.         else
    56.             _label.text = "Just item";
    57.     }
    58. }
    59.