MarimerLLC / cslaforum

Discussion forum for CSLA .NET
https://cslanet.com
Other
31 stars 6 forks source link

DevExpress MVVM Conflict #455

Open CrossSlide opened 6 years ago

CrossSlide commented 6 years ago

I’m trying to use DevExpress MVVM framework for my WPF application. As suggested in the CSLA4 book, I’ve created a ViewModel class derived from the ViewModelBase. It’s a copy straight from the book but I have commented out the Bxf.Shell code.

So, I add the ViewModel to the public class MyDXViewModel : ViewModel<MyCSLAobj> and compile, start the app and I get this error.

ViewModelSourceException: Class already supports INotifyPropertyChanged, but RaisePropertyChanged(string) method not found: MyDXViewModel

I’m guessing the ViewModel is conflicting with their mvvm methods somehow. Can anyone help?

tfreitasleal commented 6 years ago

Hi,

I had to solve this kind of problem when creating a Csla.Xaml adapter for Caliburn.Micro MVVM framework. You can find the final result at CslaContrib. I won't tell you how I solved it, because I typed a lot of unnecessary code.

Developing the MvvmFx framework (WinForms) I found a much easier way to do it. You can find the final result at MvvmFx. And that's what I suggest.

To create a CSLA ,NET adapter for DevExpress, you need to create a replacement class for ViewModelBase. By the way, you should follow DevExpress naming. For instance, Caliburn.Micro uses the name Screenso the new ViewModelBase class was named ScreenWithModelBase.

For this replacement ViewModelBase class, do not derive from Csla.Xaml ViewModelBase but from the DevExpress equivalent. Then add the missing methods needed by CSLA .NET. What are those methods? Not the INotifyPropertyChanged implementation as you should use the implementation that comes with DevExpress.

Csla.Xaml ViewModelBase replacement needs to support the "Verbs" present on ViewModel<T>. So you need to create the methods

Of course this isn't as simple as it sounds, because you have to take care of things like ManageObjectLifetime. Merging the code in Csla.Xaml.ViewModelBase<T> should do it, provided you take care of replacing OnPropertyChanged with the DevExpress equivalent.

After the ViewModelBase replacement, you need to create the new ViewModel - the class with the "verbs". Just copy the Csla.Xaml.ViewModel class. This new class is the one you will inherit on your concrete ViewModels.

One final note. The CSLA .NET adapter for Caliburn.Micro in CslaContrib is a bit incomplete as it includes only the ScreenWithModelBase and ScreenWithModel. In fact Caliburn.Micro uses a lot of other interesting classes that should also have a CSLA .NET adapter. To make these classes (Conductor classes) work with CSLA .NET, all those classes should have been re-written in order to make them inherit or useScreenWithModel and merge the Caliburn.Micro code.

I guess this last remark is a bit cryptic for those who don't know Caliburn.Micro. The important thing here is that, depending on DevExpress MVVM framework features, you may need to adapt CSLA .NET to other classes that inherit from DevExpress ViewModelBase equivalent.

This post is quite long and maybe not as clear and understandable as I wanted. In doubt, please feel free to ask.

Now it would be really really nice if you publish your final result on CslaContrib.

CrossSlide commented 6 years ago

Wow @tfreitasleal thanks for the in-depth answer! This seems like a huge undertaking that may well be outside of my skill set (new to C#).

DevExpress offers two ways to implement ViewModels. One with their ViewModelBase and one they call POCO View Model. The POCO seemed to be the easiest and that’s the one I’ve been trying to implement. When I told them about the RaisePropertyChanged error (see above) they said if your class already implements INotifyPropertyChange then just add “public virtual void RaisePropertyChanged(string propertyName) { }”.

I did mention this was a CSLA object and their response seemed like this should be doable. Unfortunately I can’t quite figure out how to properly wire the RaisePropertyChanged method in the final DX model class.

What do you think?

CrossSlide commented 6 years ago

Ok, here is a fix for DevExpress/CSLA MVVM ViewModelBase conflict. It seems to be working fine.

[POCOViewModel]
public class MyDevExpressViewModel : MyViewModel<MyCSLAObj>
{
    // FIX: CSLA ViewModelBase inherits DependencyObject where ClearValue methods conflict with the DevExpress POCO transformation process
    public static void BuildMetadata(MetadataBuilder<WorkOrderVM> builder)
    {
        builder.CommandFromMethod(x => x.ClearValue(default(DependencyProperty))).DoNotCreateCommand();
        builder.CommandFromMethod(x => x.ClearValue(default(DependencyPropertyKey))).DoNotCreateCommand();
    }
}