Ninject Custom Inject Attribute - attributes

Could someone point me in the direction of how to create a custom "Inject" attribute with Ninject?
I would like to do the following:
InjectView - custom "inject" attribute
When a property with this attribute is to be injected, the injected value is to be loaded from a "ViewManager" class.
I found an example with ISelector to decide if the property / filed is to be injected, however I couldn't find out how to add a custom "injection strategy" for this - I would like to delegate the injection of the actual value to my ViewManager.

It's already supported and can be done with a simple configuration of the kernel.
new StandardKernel(new NinjectSettings() { InjectAttribute = typeof(MyOwnInjectAttribute) };

I solved this by adding a custom IInjectionHeuristic which allows injecting by my custom attribute. Then I also added a custom IBindingResolver which adds an additional binding per type that is resolved - this binding has a condition checking for the custom attribute, so that it doesn't break any previous bindings...
Tha bindings created by the custom IBindingResolver sets a local "ProviderCallback", which utilizes the extracted property and passes the request to an internal ViewRegionManager instance.
Hope this helps in case anyone wants to do something similar in the future.

Related

How to know when a property has been updated from it's connected attribute?

Given:
#property({type: Boolean, attribute: 'some-attr'}) someAttr = false;
I was expecting to see updated being fired once 'some-attr' value gets updated in the DOM.
However, updated doesn't get fired at all.
Is my expectation wrong, or should I set things up differently?
Looking at Elm's discussion of properties vs attributes, the documentation of the Html.Attributes module's attribute function, and the Elm documentation on custom elements, I am pretty sure, that this is caused by simply binding an elm expression to attribute some-attr of the LitElement based custom element. I.e. the DOM attribute will always be present and hence the corresponding property always be true.
The default converter for Boolean (activated by providing type:Boolean to the decorator) mimicks the behaviour of HTML attributes used as flags (e.g. disabled on an <input> element): If the attribute is present (no matter the value), the flag is set (true). The implementation is really straight forward, if you want to look at it in the sources: https://github.com/Polymer/lit-element/blob/master/src/lib/updating-element.ts#L163
I see these options for your problem:
Implement some extra logic in Elm to add / remove the presence of the attribute.
Create your own attribute converter for the LitElement based custom element.
Use another default converter (e.g. for String, the "default" default converter) and implement the custom logic inside the LitElement (e.g. using a derived value).
Of these 3 options, I would generally recommend the first one, as your custom element then still behaves naturally, i.e. if some-attr should be a flag (boolean attribute), then following which HTML semantics, it should be defined by its presence, not its value. This allows you to re-use it in other projects without surprising other developers.
That being said, there may of course be project-specific requirements, that are more important. E.g. if you only use this custom element in this one project with Elm, your road to success may be faster going for options 2 or 3.

Passing a POJO to a custom control property

I'm refactoring an XPages application which has five nested repeat controls repeating basically the same thing (an xp:panel). I thought, aha, here comes a custom control with properties!
I'm looping my repeat controls around properties of a managed bean, and I was hoping I could have set a property for the custom control to just accept the POJO I'm sending it (and then access it with EL within the custom control).
What should I do? Make the custom control receive only strings, numbers, etc and have the whole nested-control logic outside? Or is there a trick?
A custom control can easily accept a java object that's passed in via the custom properties. Just use the type: java.lang.Object
All the answers were correct, but only David put it as an answer - thanks to all!
I've noted my code here for anyone later: I defined node to be of Type java.lang.Object. Notice the syntax to get the object into the custom control:
<xp:repeat
id="repeatfirstlevelnode"
value="#{TableOfContents.root.children}"
var="firstlevelnode">
<xc:ccPanelNavigation
node="#{firstlevelnode}"
panelStyleWhenActive="panelLevel1 active bold"
panelStyleWhenInactive="panelLevel1"
NameNestedRepeatControl="repeatsecondlevelnodes">
</xc:ccPanelNavigation>
And once you're in the custom control, you access the property with CompositeData.YourObject.
<xp:image
id="imgDummy"
url="/dummyEC.png"
styleClass="imageDummy">
<xp:this.rendered><![CDATA[#{not compositeData.node.hasChildren}]]></xp:this.rendered>
</xp:image>

How to get UIVisualizer to use the View Model passed to it

I'm attempting to create view/viewModel pair to act as a MessageBox replacement which will be called by the UIVisualizer Service. The viewModel has five different constructors, one being the default, and the others to define the different attributes of the MessageBox(e.g. Type, Image, Message, Title, etc.). I will be creating the viewModel using one of the four non-Default constructors each time I desire a MessageBox to popup. I am doing this versus using the built-in MessageService is because I'm using third party controls for my application and I want the MessageBox look-and-feel to match the rest of the application.
My problem is that even though I'm creating the viewModel, Catel is not using the viewModel I pass in to UIVisualizer, but is creating a new viewModel from the default constructor.
Does anybody know how to get this behavior to stop.
The best thing to do is create your own version of the IMessageService (create new class deriving from MessageService and override the Show method).
Catel should re-use the passed in view model. If you think you have found a bug, please report it at http://www.catelproject.com/support/issue-tracker

ViewModel for nested control not refreshing in Catel MVVM for WPF

I have a nested control (NC1) which contains 3 instances of NC2. When the containing view is first opened, NC1 will be null and so the three instances of NC2 will be null. This appears to work correctly based on debugging through my code and the framework.
When a selection is made in the containing view NC1 is properly set (and the ViewModel is (re)created) and values for its properties (exposed through Fody.Expose) appear in the view. However, none of the ViewModels for NC2 are (re)created and they do not reflect the values provided by their respective models.
I am not sure exactly what information to provide without uploading a lot of content, so I will take a stab.
In the NC1 view, I have the following
<localViews:NC2 DataContext="NC2Entry1"/>
<localViews:NC2 DataContext="NC2Entry2"/>
<localViews:NC2 DataContext="NC2Entry3"/>
NC2EntryX are properties on the NC1 ViewModel that return a specific instance of an NC2 model from a list. The NC2EntryX properties is NOT registered with RegisterProperty.
As a note, I have discovered that I must have an empty parameter constructor for the NC1 and NC2 view models. If I do not, then I receive a MissingMethod exception when the view model is being created when the TypeFactory attempts to create the ViewModel with the Activator instead of using the injection path. The injection path is not used because the call at line 591 of TypeFactory returns false because the NC2 model passed is 'not registered'. (Not sure if it should be or how to make it so.)
I am using Catel version 3.9.0
The NC2EntryX property changes must be reflected to the view somehow. You can do this by making it Catel properties, or by calling RaisePropertyChanged("NC2EntryX") yourself when setting the property value. Only in that case the view will be updated (this is just standard WPF / MVVM behavior).
About the missing method exception: it is a first chance exception where the TypeFactory tries to fall back to Activator.CreateInstance when it fails to create the type with dependency injection. No need to worry about this. If you don't want view models to be alive without a model, don't create an empty constructor.

How to override context.getUser()

for a my current project I would like to overide the context.getUser() method to return a custom pojo which extends the default object returned?
The reason I would like to do is so that I dont have to use the sessionScope technique of saving person specific data and just can call context.getUser() instead (which checks which user is logged on (or anonymous) and retrieves all data needed without.
I would not override context.getUser() - you don't know what else that may require. Have you looked at the userBean and or peopleBean from the extension library? You could use that to get any information you need, then if you need more, or want to create a custom class that extends those beans, install it as a scoped bean in your application, and then use it as the base for your own getUser().

Resources