I'm using CSLA latest release and trying to add a row with default items to the collection. What I've noticed is the default constructor of the Foo class is called instead of the AddNewCore in the FooList Class. I am unable to get the AddNewCore or the Child_Create methods to get invoked when a new row is added in a XamDataGrid row. (A row is added, but it is from the default constructor of the FooLine Class--i.e. no default values and no MarkAsChild attribute.) Here is the code snippet that is in the FooList class:
protected override FooItem AddNewCore()
{
var item = DataPortal.CreateChild<FooItem>();
MarkAsChild();
Add(item);
return base.AddNewCore();
}
protected override void Child_Create()
{
var item = DataPortal.CreateChild<FooItem>();
MarkAsChild();
Add(item);
base.Child_Create();
}
What am I doing wrong?
AddNewCore() method exists in client side CSLA class 'ExtendedBindingList' with 'void' return type and same method is exists in server side class 'ObservableBindingList' with return type 'ListClass'. So we required to call run time client side method from server side.
Please refer below code for the same.
#if SILVERLIGHT
protected override void AddNewCore()
{
var item = DataPortal.CreateChild<FooItem>();
Add(item);
}
#endif
For information: The reason the above code does not work has to do with the way WPF invokes the New method. Typically, in other frameworks it is possible to hook on to that event, intercept it, and return with default data. With WPF, it is necessary to check the RecordAdding, or RecordAdded trigger events and process the invocations by hand.
In my case, the WPF would look like:
<i:Interaction.Triggers>'
i:EventTrigger EventName="RecordAdded">
<ei:CallMethodAction TargetObject="{Binding}"
MethodName="CreateDefaultAddressValuesCommand" />
</i:EventTrigger>
In the view model:
var idx = FooInformation.FooAddressList.Count - 1;
var address = await FooAddress.CreateAsync();
FooListing.FooAddressList[idx] = address;
Related
Let's say in my component I have simple computed array of items, all of which are type of custom class Item. Item is an object of a custom class with private methods.
// items is a computed array
const items = computed(() => [new Item("first"), new Item("second"),...]);
// item class
class Item{
constructor(itemName){
this.itemName = itemName;
this.inStock = this.#itemInStock(itemName);
// other properties initialized by some other private methods
}
#itemInStock(item){
return items.indexOf(item) !== -1;
}
}
Now I have been reading about reactivity, here, and if I understood vue uses Proxies to catch attempt to read property and Reflects to use binding, but will it catch methods as well? Can I use private methods in class instance and then use that class instance in template?
Private methods should not be accessed directly e.g. Item.itemInStock should fire error.
Please note that I don't intent to use any of my methods directly in template nor anywhere in application (that is why I made them private)
you can use method reactive and toRefs.
first, you can import this methode.
import { reactive, toRefs } from 'vue
second, you change on your computed
const items = computed(() => reactive[new Item("first"), new Item("second"),...]);
and you change return with
return toRefs(items.indexOf(item))
if your data is object, you should add spread in your return
return ...toRefs(items.indexOf(item))
I want to achieve two goals:
I want my model to be loaded every time from the DB when it's in a life-cycle (for every request there will be just one request to the DB)
I want my model to be attached dynamically to the page and that wicket will do all this oreable binding for me
In order to achieve these two goals I came to a conclusion that I need to use both CompoundPropertyModel and LoadableDetachableModel.
Does anyone know if this is a good approach?
Should I do new CompoundPropertyModel(myLoadableDetachableModel)?
Yes, you are right, it is possible to use
new CompoundPropertyModel<T>(new LoadableDetachableModel<T> { ... })
or use static creation (it does the same):
CompoundPropertyModel.of(new LoadableDetachableModel<T> { ... })
that has both features of compound model and lazy detachable model. Also detaching works correctly, when it CompoudPropertyModel is detached it also proxies detaching to inner model that is used as the model object in this case.
I use it in many cases and it works fine.
EXPLANATION:
See how looks CompoundPropertyModel class (I'm speaking about Wicket 1.6 right now):
public class CompoundPropertyModel<T> extends ChainingModel<T>
This mean, CompoundPropertyModel adds the property expression behavior to the ChainingModel.
ChainingModel has the following field 'target' and the constructor to set it.
private Object target;
public ChainingModel(final Object modelObject)
{
...
target = modelObject;
}
This take the 'target' reference to tho object or model.
When you call getObject() it checks the target and proxies the functionality if the target is a subclass of IModel:
public T getObject()
{
if (target instanceof IModel)
{
return ((IModel<T>)target).getObject();
}
return (T)target;
}
The similar functionality is implemented for setObject(T), that also sets the target or proxies it if the target is a subclass of IModel
public void setObject(T object)
{
if (target instanceof IModel)
{
((IModel<T>)target).setObject(object);
}
else
{
target = object;
}
}
The same way is used to detach object, however it check if the target (model object) is detachable, in other words if the target is a subclass if IDetachable, that any of IModel really is.
public void detach()
{
// Detach nested object if it's a detachable
if (target instanceof IDetachable)
{
((IDetachable)target).detach();
}
}
I have an issue when I compile the user interface, when i add a method messages.usuario(), Firebug show the error : TypeError: null has no properties
lblUsuario = new Label_2(null.nullMethod()); this is the code of my class :
public class AdministradorMVP implements EntryPoint {
private MessageConstants messages;
#Inject
public void setMensajes(MessageConstants mensajes) {
this.messages = mensajes;
}
private final MyWidgetGinjector injector = GWT.create(MyWidgetGinjector.class);
private Place defaultPlace = new SignInPlace("Admin");
private SimplePanel appWidget = new SimplePanel();
/**
* This is the entry point method.
*/
Label lblUsuario = new Label(messages.usuario());
Label lblNombre = new Label(messages.nombre());
so I can't find the source of the problem, thank you
The GWT compiler generates null.nullMethod() whenever it can statically determine that a particular method is always called on a null reference. In this case, messages has been determined to always be null (either setMensajes is called with a null value or it's not called at all), so messages.usuario() would always throw a NullPointerException, and this is translated into a null.nullMethod() in the generated JavaScript code.
From your code I'm missing the 'boostrap the injection' (see JavaDoc of Ginjector). In other words, you need to trigger the initial inject to take place. Creating MyWidgetGinjector is not enough.
One solution is to add a method void inject(AdministradorMVP entryPoint); to the interface MyWidgetGinjector and in the class AdministradorMVP in onModuleLoad call as (one of) the first statements: injector.inject(this);.
Whenever I call ShowViewModel, somehow a ViewModel and a View of the requested types are retrieved and are bound together for display on the screen. When are new instances of the ViewModel and View created versus looked up and retrieved from a cache somewhere? If new instances are always created and I choose to make my own cache to prevent multiple instances, then how do I show my cached ViewModel instance?
When are new instances of the ViewModel and View created versus looked up and retrieved from a cache somewhere?
Never - for new navigations the default behaviour is always to create new instances.
if... how do I show my cached ViewModel instance?
If for whatever reason you want to override the ViewModel location/creation, then there's information available about overriding the DefaultViewModelLocator in your App.cs in:
MVVMCross Passing values to ViewModel that has 2 constructors
http://slodge.blogspot.co.uk/2013/01/navigating-between-viewmodels-by-more.html
Put simply, implement your code:
public class MyViewModelLocator
: MvxDefaultViewModelLocator
{
public override bool TryLoad(Type viewModelType, IDictionary<string, string> parameterValueLookup,
out IMvxViewModel model)
{
// your implementation
}
}
then return it in App.cs:
protected override IMvxViewModelLocator CreateDefaultViewModelLocator()
{
return new MyViewModelLocator();
}
Note that older posts like How to replace MvxDefaultViewModelLocator in MVVMCross application are still conceptually compatible - but the details in those older posts are now out of date.
In MvvmCross v3.5 you can use this Class:
public class CacheableViewModelLocator : MvxDefaultViewModelLocator{
public override IMvxViewModel Load(Type viewModelType, IMvxBundle parameterValues, IMvxBundle savedState)
{
if (viewModelType.GetInterfaces().Any(x=>x == typeof(ICacheableViewModel)))
{
var cache = Mvx.Resolve<IMvxMultipleViewModelCache>();
var cachedViewModel = cache.GetAndClear(viewModelType);
if (cachedViewModel == null)
cachedViewModel = base.Load(viewModelType, parameterValues, savedState);
cache.Cache(cachedViewModel);
return cachedViewModel;
}
return base.Load(viewModelType, parameterValues, savedState);
}}
in your App Code override this method:
protected override IMvxViewModelLocator CreateDefaultViewModelLocator(){
return new CacheableViewModelLocator();}
Create an interface "ICacheableViewModel" and implement it on your ViewModel.
Now you can share the same ViewModel instance with multiple Views.
My database has a 'LastModifiedUser' column on every table in which I intend to collect the logged in user from an application who makes a change. I am not talking about the database user so essentially this is just a string on each entity. I would like to find a way to default this for each entity so that other developers don't have to remember to assign it any time they instantiate the entity.
So something like this would occur:
using (EntityContext ctx = new EntityContext())
{
MyEntity foo = new MyEntity();
// Trying to avoid having the following line every time
// a new entity is created/added.
foo.LastModifiedUser = Lookupuser();
ctx.Foos.Addobject(foo);
ctx.SaveChanges();
}
There is a perfect way to accomplish this in EF 4.0 by leveraging ObjectStateManager
First, you need to create a partial class for your ObjectContext and subscribe to
ObjectContext.SavingChanges Event. The best place to subscribe to this event is inside the OnContextCreated Method. This method is called by the context object’s constructor and the constructor overloads which is a partial method with no implementation:
partial void OnContextCreated() {
this.SavingChanges += Context_SavingChanges;
}
Now the actual code that will do the job:
void Context_SavingChanges(object sender, EventArgs e) {
IEnumerable<ObjectStateEntry> objectStateEntries =
from ose
in this.ObjectStateManager.GetObjectStateEntries(EntityState.Added
| EntityState.Modified)
where ose.Entity != null
select ose;
foreach (ObjectStateEntry entry in objectStateEntries) {
ReadOnlyCollection<FieldMetadata> fieldsMetaData = entry.CurrentValues
.DataRecordInfo.FieldMetadata;
FieldMetadata modifiedField = fieldsMetaData
.Where(f => f.FieldType.Name == "LastModifiedUser").FirstOrDefault();
if (modifiedField.FieldType != null) {
string fieldTypeName = modifiedField.FieldType.TypeUsage.EdmType.Name;
if (fieldTypeName == PrimitiveTypeKind.String.ToString()) {
entry.CurrentValues.SetString(modifiedField.Ordinal, Lookupuser());
}
}
}
}
Code Explanation:
This code locates any Added or Modified entries that have a LastModifiedUser property and then updates that property with the value coming from your custom Lookupuser() method.
In the foreach block, the query basically drills into the CurrentValues of each entry. Then, using the Where method, it looks at the names of each FieldMetaData item for that entry, picking up only those whose Name is LastModifiedUser. Next, the if statement verifies that the LastModifiedUser property is a String field; then it updates the field's value.
Another way to hook up this method (instead of subscribing to SavingChanges event) is by overriding the ObjectContext.SaveChanges Method.
By the way, the above code belongs to Julie Lerman from her Programming Entity Framework book.
EDIT for Self Tracking POCO Implementation:
If you have self tracking POCOs then what I would do is that I first change the T4 template to call the OnContextCreated() method. If you look at your ObjectContext.tt file, there is an Initialize() method that is called by all constructors, therefore a good candidate to call our OnContextCreated() method, so all we need to do is to change ObjectContext.tt file like this:
private void Initialize()
{
// Creating proxies requires the use of the ProxyDataContractResolver and
// may allow lazy loading which can expand the loaded graph during serialization.
ContextOptions.ProxyCreationEnabled = false;
ObjectMaterialized += new ObjectMaterializedEventHandler(HandleObjectMaterialized);
// We call our custom method here:
OnContextCreated();
}
And this will cause our OnContextCreated() to be called upon creation of the Context.
Now if you put your POCOs behind the service boundary, then it means that the ModifiedUserName must come with the rest of data from your WCF service consumer. You can either expose this
LastModifiedUser property to them to update or if it stores in another property and you wish to update LastModifiedUser from that property, then you can modify the 2nd code as follows:
foreach (ObjectStateEntry entry in objectStateEntries) {
ReadOnlyCollection fieldsMetaData = entry.CurrentValues
.DataRecordInfo.FieldMetadata;
FieldMetadata sourceField = fieldsMetaData
.Where(f => f.FieldType.Name == "YourPropertyName").FirstOrDefault();
FieldMetadata modifiedField = fieldsMetaData
.Where(f => f.FieldType.Name == "LastModifiedUser").FirstOrDefault();
if (modifiedField.FieldType != null) {
string fieldTypeName = modifiedField.FieldType.TypeUsage.EdmType.Name;
if (fieldTypeName == PrimitiveTypeKind.String.ToString()) {
entry.CurrentValues.SetString(modifiedField.Ordinal,
entry.CurrentValues[sourceField.Ordinal].ToString());
}
}
}
Hope this helps.
There is a nuget package for this now : https://www.nuget.org/packages/TrackerEnabledDbContext
Github: https://github.com/bilal-fazlani/tracker-enabled-dbcontext