Architectural question regarding Interfaces implementation and extensibility - c#

I've created a sample app, just to test and try out some of wpf's capabilities. I was basically trying out the databinding in wpf, and did the rest of stuff more or less quickly. THen, i faced an arquitectural problem (yes, should have thought in advance before starting coding :) ) and i wanted to know what's the best refactoring solution for it.
I have a simple interface that returns a list of objects, based on a defined process.
public interface IDoStuff<out T>
{
IEnumerable<T> Do(string someParam);
}
i've created a couple of implementations for this interface. Then i have a view in wpf, which has a dropdown with hardcoded values, and depending on what you select, instatiates the implementation of the interface and populates some list
foreach (var item in new IDoSTuffImplementation1()<MyObj>.Do("imp 1"))
{
MyObjs.Add(item);
}
ater on MyObjs is the DataContext for a listview, and displays things and so on and so forth, but it's out of the main question.
this is all hardcoded and not very nice. If i was ever to implement a new interface, i'd need to add it to the dropdown, and create a new foreach for that specific implementation (more duplicated code)
Ok, here's my impression on making this better/refactoring for extensibility.
I was thinking a good approach would be to use some kind of MVVM pattern, making the wpf view into a view + viewmodel. the viewmodel would use some kind of IoC like spring, which would (by xml) instantiate one specific implementation of the interface, and inject it to the viewmodel, which would then call its "Do" method and everyone happy. So this way, the only thing that would be needed to do when we implement a new component, is to add it to the xml config file.
Suggestions, Comments? what's the best approach, if any?
thanks!!

Actually I don't see any architecture changes if you provide another implementation of the interface. You already have a good architecture when using MVVM, so the task you are trying to accomplish will not change the architecture, but will extend your application using the architecture.

I suggest you change you Method to a Property instead. And assign that property to ComboBox's ItemsSource property to ease up your coding using data binding.

Related

Use same viewmodel different windows

My project is build on MVVM. Currently I have a list where i can select an object and add them to another list. What I want to make is a new window where this list is shown (the list with objects that are added) and edit that list in the new window (delte an item from that list).
How should I pass the data (selected object) to another window and be able to update them there?
I currently have it working in one view. In some related questions they advice MVVM light so I tried looking for that, from what I red mvvm light is mostly used to replace the notify property change. Should I use mvvm light or are there some specific patterns I could use?
Both windows will be open at the same time.
If you want to share your ViewModel between windows, you can use a ViewModelLocator. It is not specific to MvvmLight, it just creates one for you with its project template. You can implement it yourself, it is basically a container for your ViewModels. You can look here for the implementation details.
I've got to say that I'm not sure that these are the best approaches and if they are common, it's just what me and my colleagues were using in a WinRT application, so I'll be really glad if someone comes up with something better (both of these are not that clean).
I can think of two ways to pass data (without persisting it)
Pass parameters on page navigation
Have common shared class (Static or singleton class with some common data accessible from all ViewModels)
For passing on navigation:
I have this method in my Navigation service class:
public virtual void NavigateTo(Type sourcePageType, object parameter)
{
((Frame)Window.Current.Content).Navigate(sourcePageType, parameter);
}
and I use it like this in navigation commands:
Navigation.NavigateTo(typeof(PageType), someParameters);
Then you could get the values in the code behind of the navigated page
protected override void OnNavigatedTo(NavigationEventArgs e)
{
var receivedParameter = e.Parameter as TheTypeOfThePassedParameter;
}
And from there to pass them to the ViewModel, maybe there is an option to pass this without code in the code behind but I've not tried this.
Having shared class:
This is pretty much straightforward just have static class or a singleton with the desired fields.

Defining properties of UI using Attributes

For a new project, I was recently asked to investigate a method of attaching information related to UI rendering to business objects in a WPF application. For example a report class:
class ExecutionReport
{
[Displayable(Bold, Background=Color.Red)]
public String OrderId{get; private set;}
[Displayable(Normal, HAlignment=Center)]
public String Symbol {get; private set;}
// this should be hidden as it doesn't have DisplayableAttribute
public String ClientOrderId {get; private set;}]
[Displayable(Normal, HAlignment=Right,
Format("If [Position] < 0 then Background=Color.Red"),
Format("If [Position] > 0 then Background=Color.Lime"),
DisplayFormat("+#;-#;0")]
public Int Position {get; private set;}
}
This is a very new approach for me as typically in most wpf MVVM applications I have worked on there has been a clear separation of the view and viewmodel and I strive as much as possible to keep UI specific details out of the VM. Instead I would lean towards writing this using resource dictionaries and simple converters applied on the bindings in the view layer.
My questions are: Are there any wpf/mvvm frameworks out there that use this kind of an implementation? If so I'm curious to see how it would be achieved.
Are there any obvious pitfalls? The first couple things that come to my mind are
Change notification (ie. INotifyPropertyChanged to trigger an update of the view). Would the implementation of this be a lot harder now?
Difficulty in being able to leverage resource dictionaries for system wide values. For example, maybe I wanted to change the color of red being used throughout the application. I would have to ctrl + f through and find every place in business objects where it was used and change it instead of being able to modify a single StaticResource
Inability to leverage DesignTime DataContexts
Performance. Seems likes this would require heavy use of reflection which might not be as performant as typical value converters
I'm very interested to see if I'm correct on the second and third points or if both of these things could still be acheived?
Ultimately I feel that this is a bad design and I'm leaning towards writing a different implementation to show the interested party how I would typically approach this kind of problem. Just want to make sure I'm not missing something obvious that might actually make this more elegant.
IMO this seems like a horrible idea, they all seems like examples that should be implemented as XAML converters.
All of the points list seem to be valid reasons to avoid doing this.
Note: There are a set of attributes in the framework which provide some UI functionality already (very limited), see the System.ComponentModel.DataAnnotations namespace.
This approach is very popular and it's called aspect oriented programming (ASP.NET MVC leverages it a lot). The most popular library to write this fast is PostSharp (see customers case studies, there are some companies which have used it for WPF). The best thing in PostSharp is that uses compile-time weaving.
For the first point:
PostSharp got well tested NotifyPropertyChanged aspect, you can add [NotifyPropertyChanged] attribute to class and all properties will call PropertyChanged when value gets changed.
For the second point: you can always make your attribute to look for StaticResources and pass resource key in attribute.
For the third (although I'm not 100% sure about it) and fourth point: compile time weaving means that aspect is "appended" to code on compilation - like you would have written it inside method/property to which you have appended attribute. It's like post-build compiler and doesn't use reflection (if aspect you wrote doesn't use reflection) so performance is really good.
However in example you gave I'd rather go with value converters and styles like #AwkwardCoder said - but aspects(attributes) are also useful with "view" for example: they're great for validiation.
I agree that this seems like a horrible idea, and your comment ...
in most wpf MVVM applications I have worked on there has been a clear
separation of the view and viewmodel and I strive as much as possible
to keep UI specific details out of the VM. Instead I would lean
towards writing this using resource dictionaries and simple converters
applied on the bindings in the view layer
... I think sums up why and how to avoid it.
Tying your business objects directly to implementation details such as colour, horizontal alignment, or position, seems like a short-term win (but long term hell).

Using MVVM with CollectionViewSource

I'm trying to use CollectionViewSource to display some data, and all the examples/tutorials I've seen have a custom class built, which they use in another class, which inherits from ObservableCollection. I'm new to both using CollectionViewSource and this is only my third implementation of MVVM, so I might misunderstand the programming pattern, but my question is:
where do I put the ObservableCollection class and/or custom class?
I feel like they should go in the Model, but then I'm not sure what gets bound to the View. Do I just build these as external classes, and then reference them in Model/ViewModel?
Any help is appreciated
Firstly, I would say that there is no need to inherit from ObservableCollection<T> unless you are adding functionality to it which I have rarely, if ever, actually needed to do.
In most cases I create ViewModel properties of type ObservableCollection<T> and then populate them from the Model whenever I load the data. This has the advantage that the Model does not need to use ObservableCollection<T> (it can be any IEnumerable<T>) and it means that later when I (almost inevitably) want to wrap whatever I'm getting back from the Model in another instance-specific view model I am only obliged to change my existing view model classes.
Once you have a property on your view model you can simply bind your CollectionViewSource to that property and it will do everything from there. It's worth noting that the CollectionViewSource doesn't actually care about the type of the property, so you can expose your collection to the View as an ICollection<T>, IEnumerable<T> or (I believe) even as an object and the CollectionViewSource will still treat it the same as if it is exposed as an ObservableCollection<T>.
Sorry for the slightly rambling answer. The concise version would be "it depends on the situation" but I tend to follow this general approach in most cases.

MVVM and DI - How to handle Model objects?

I'm using Caliburn and C#, but I feel like this is a generic MVVM/DI question.
Let's say I have a view model, NoteViewModel, that is passed a model object called Note.
Here is some code:
class NoteViewModel : PropertyChangedBase
{
private readonly Note _note;
public NoteViewModel(Note note)
{
_note = note;
}
public string Title
{
get { return _note.Title; }
set { _note.Title = value; NotifyOfPropertyChange(() => Title); }
}
}
Right now this object is created by calling new() and passing a model object.
Well, that works great, but now I need to add a method that requires an imported class from my DI container.
So do I merely call ServiceLocator.Current.GetInstance() to get it? Or should I design this view model to be created via the DI container and somehow setup a way to pass a Note object?
What is the proper way to design this view model? Basically a "PerInstance" view model that requires a model object for it's use. Does Caliburn have a built-in way to do this?
Caliburn has an interface (IHaveSubject and its typed version IHaveSubject) addressing this kind of scenario: basically it allows a mean to configure the ViewModel with a "subject" after its instantiation, tipically through the container:
class NoteViewModel : PropertyChangedBase, IHasSubject<Note> {
...
}
myNoteViewModel = ... //obtain an instance
myNoteViewModel.WithSubject(new Note());
This solution also integrates well with ISubjectSpecification / Conductor
infrastructure.
Even though post-construction initialization is a simple and effective solution, you may not want (from a pure design perspective) to renounce to an explicit constructor parameter to enforce the need for a Note to istantiate the ViewModel.
In this case I think you have to leverage peculiar features of your DI container, because you may have some parameters of the constructor representing a "real" input parameter, while other may be service dependencies.
Castle Windsor, for example, has a nice feature allowing you to quickly build an explicit (typed) factory for your ViewModel; the factory method will only allow to set the "real" parameters, while all dependencies are managed by the container (see this post for an extensive description of this Windsor feature: http://kozmic.pl/archive/2009/12/24/castle-typed-factory-facility-reborn.aspx)
Can you solve it using hierarchical view models?
To me it becomes more and more clear that I need one ViewModel per View and one ViewModel per model item or collection when building larger application.
That way we can build up ViewModels hierarchically, matching the XAML hierarchy.
The required objects can be defined or injected at the top level by app's main view model then. The nested view models can then access anything the way you design it to make things reachable by them.
About Caliburn, I don't know any specific things about that framework, sorry.
I'm using the ServiceLocator also. And I also "feel dirty" in doing this. But I have resolved to use the YAGNI principle and keep this pattern until I find a compelling payback to the complexity of adding 5 IServices into my constructors, passing them up via 3-4 layers of inheritance to the base classes in which they are needed, and creating everything via the container. Of course my app is evolving, and YAGNI doesn't always last...

Design Question

I have a control in which we show some links to different sites based on some business rules. Currently all business logic to build link list is in control.
I plan to move out the busincess logic from the control.
what will be a good design for this?
can I use any design pattern?
You shouldn't get too caught up in thinking about patterns. Most of the time they are overkill and add too much complexity. Particularly with a trivial scenario like this.
Just utilize good object-oriented practices and you'll be fine. Encapsulate your business logic in another class and provide public properties for your control to access it. Keep it simple!
How about the Model-View-Presenter pattern?
Another good choice might be the Mediator pattern.
Do you really need a custom control for this?
Model-View-Controller suggests that you only have display logic in a control.
Find a solution that allows you to make small changes to a built in control (ListView) and create a custom data set somewhere else to pass to it.
I not sure how you implement your business rules but here is an idea...
I would databind your web forms list control.
public class YourLinks
{
// You could do it by overloading the constructor...
// Again not sure how you determine what links should be displayed...
// If you had consistent types you could make your constructor internal
// and then create a YourLinkBuilder see below...
public YourLinks(User user, Region region)
{
}
public YourLinks(City city)
{
}
// Databind to this method...
public IEnumerable<string> GetLinks()
{
// return your links...
}
}
public class YourLinkBuilder
{
public static YourLinks BuildPowerUserLinks()
{
return new YourLinks(new PowerUser(), new Region("Washington"));
}
public static YourLinks BuildVisitorLinks()
{
return new YourLinks(new VisitorUser(), new Region("Empty"));
}
}
Given the little information provided, I would suggest you create a model of just the links (and its related data). So that you can pass the LinksModel to your views for rendering. Or pass your LinksModel to your existing model (as a sub-model).
Either way, all this data is encapsulated. So if you want to add data to it later, it will not change your method signatures (or general contract). If you want to remove data from it, same advantage. If you want to remove it entirely, its only one object and simplifies the removal.
You can also build links view renderers so that it and only it knows how to visually display the LinksModel. So within your view, you can delegate the visual aspects of the links info to such renderers instead of having logic within your existing view. If you want to change how links view looks later or want to give the user the power of selecting different renditions, you can simply use different renderers rather than jamming your entire code with 'if' blocks.
Jeach!
You should use Model-View-Presenter for sure. In the view, you should have your control.
The control's responsibility should be merely to take input from the user, validate it, and pass that information to the presenter. The presenter should then interact with the model, where your business rules are stored.
From the model, you may wish to return the links that are then passed to the control for display, or you may wish to return some metadata that is passed to another system to retrieve the links.
What I would do is use the Strategy pattern in the model, so that you can easily swap in and out different versions of your business rules.
To abstract interaction with your backend datasource (if you have one) have a look at Martin Fowler's Gateway pattern.

Categories

Resources