What is the best way to let a child class communicate with the parent class - oop

my question is, what is the best way to let a child class communicate with the parent class.
For example:
I have a main class simply called Main, and another class SomeClass.
Now the Main class creates an instance of SomeClass, once the state of the SomeClass-object changes, the Main class should execute different code, depending on what changed.
Yeah I know, that already sounds like the Observer design pattern, but how would I implement it with state changes treated differently?
I'm currently writing an Android app with a database to make it more specific.
In my project I have the main class, a class to connect, read from/write to the database and a GUI container class. (oversimplified, there are a few more)
The main class creates an instance of both the GUI and database class.
Now if I press a button A, it should write A-data to the database,
if I press button B, it should write B-data to the database.
As I think that a gui class shouldn't have direct access to the database, I tried other options, than just accessing the database from the gui-class
Currently, I defined a placeholder abstract class with only one method, that I am just overwriting with the functionality.
So right now I have to create a one-method-class A for the click of button A and a one-method-class B for the click of button B.
It doesn't sound like the best way to me, I mean It's working, but I'd like to improve my code, so if you have any idea, please write your solution. :)

As a good practice it is better to avoid write code in GUI class. So we can use MVVM pattern here.
Let me show a simple example for your case. This is a ViewModel class. View model does not have reference to view class:
public class YourViewModel
{
public void LoadA()
{
// here you can interact with your database
}
public void LoadB()
{
// here you can interact with your database
}
}
This is your view class. It handles button clicking, user interactions with view and forwards to the view model. It has a reference to view model.
public class YourView
{
YourViewModel yourViewModel;
public YourView()
{
yourViewModel = new YourViewModel();
}
public void ButtonA_Handler()
{
yourViewModel.LoadA();
}
public void ButtonB_Handler()
{
yourViewModel.LoadB();
}
}
If you want to handle many events, then you can try to use this approach How to: Handle Multiple Events Using Event Properties.

It seems like a good way to approach this would be to use a pattern like that described in this previous Stack Overflow answer.
They provide sample implementations there but to apply to your case, you don't need to give the GUI direct access, you can have a parent class which implements the "listener" functionality, and a child (GUI) class which just calls its parent, with those details abstracted away from the child.
If you feel like you need more details/examples on implementing this pattern see https://refactoring.guru/design-patterns/observer/java/example

Related

How to get whole viewmodel in taghelper process method?

Is it possible to get the whole view model in tag helper Process method (.NET Core MVC)?
Everything passed to the tag helper is done via attributes. If you want the whole view model, then you'd simply so domething like:
<mytag model="#Model" />
And then you'd need a property on your tag helper to bind this to like:
public MyViewModel Model { get; set; }
The name of the attribute corresponds to the name of the property. There's nothing special about "model" here.
However, the utility of that is going to be limited. Tag helpers are intended to be somewhat generic. That's the point: encapsulating reusable logic. If you tie it to a particular view model class (based on the property), then it will only work with that particular view model. The only way to make it more generic would be to use a base class or to literally type it as object, so that anything could be passed. However, with a base class, 1) you need to have every view model inherit from this base class and 2) even then, you'd only be able to use properties on the base class. With object, you wouldn't really be able to reference any properties unless you downcast it to a particular view model class first. While that would allow you to handle any scenario, in principle, you'd be forced to have long blocks of switch or if statements in your tag helper to conditionally handle different scenarios.
Long and short, it's not a great idea for many reasons to pass the whole model. The tag helper should have one specific purpose, and you should only pass things that are specifically needed by it, which also allows you to be explicit about those needs.
If you're looking for something to handle a whole model, you're more likely looking for a partial view or view component, rather than a tag helper.
The viewmodel is actually available if you bind first the for element as :
[HtmlAttributeName("asp-for")]
public ModelExpression For { get; set; }
Then you can access it in your tag helper Process or ProcessAsync through:
For.ModelExplorer.Container.Model

Error checking as navigating though UI

I have a number of objects which are used repeatedly as navigating though the pages of web application. I check each page for an error dialog as I navigate. As I repeatedly use these tests, if I do encounter an error, each test case which uses the navigation functions will fail. I don't want to maintain two sets of navigation functions so I am wondering if anyone knows of a good approach to take?
Thanks
You should not do assertions in your navigation classes. As much as I understand from you question, you have at the moment something similar to:
class Navigation{
public void navigateToSomePlace(){
navigate();
assertTrue(isInExpectedPlace());
}
}
But you should remove the validation from that method and implement it as a separate method which you can call when you need it. If you want better explanation, show some code.
Edit, how I would implement it:
class Navigation{
public void navigateToSomePlace(){
navigate();
}
public void validateIsInSomePlace(){
assertTrue(isInExpectedPlace());
}
}
So basically, when you are doing the navigation test you would call both of them, but if you only use it for navigating, you would only call the navigate()

ViewModels in ViewModelLocator MVVM Light

Is it correct to store all my ViewModels in SimpleIoc? For instance I am having three pages MainPage, Photos, Directories (therefore three ViewModels -> MainVM, PhotosVM, DirectoriesVM). Should I set DataContext in each page to View Model Property in ViewModelLocator or nest ViewModels as properties in MainVM and bind each page DataContext to Main.PhotosVMProperty, Main.DirectoriesVMProperty and so on? Could anyone explain me idea and purpose of IoC ?
First, lets look at what ViewModelLocator does and why we use it:
ViewModelLocator is declared as an object on our App.xaml page and is an application singleton. We're going to have one, and only one of them available to the application when it runs.
ViewModelLocator is the source for all our ViewModels in MVVM Light. For each ViewModel we'll have a property on the ViewModelLocator that allows us to get a ViewModel for a View. This code looks like this:
public class ViewModelLocator
{
public MainPageViewModel MainPage
{
get { return new MainPageViewModel(); }
}
}
This is a piece of my App.xaml:
<Application.Resources>
<vm:ViewModelLocator
x:Key="ViewModelLocator" />
</Application.Resources>
This is a piece from View.xaml
DataContext="{Binding MainPage, Source={StaticResource ViewModelLocator}}"
So far so good. To answer your first question, do you have to use Ioc in MVVM Light? No. There's no need as your viewmodel will be given to your view fully built and instantiated by the ViewModelLocator.
Now, onto your second question: What's the purpose of IoC?
IoC is designed to allow you to do the following:
With Mvvm Light you do the above like this:
public class ViewModelLocator
{
public ViewModelLocator()
{
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
if (ViewModelBase.IsInDesignModeStatic)
{
SimpleIoc.Default.Register<IDataService, Design.DesignDataService>();
}
else
{
SimpleIoc.Default.Register<IDataService, DataService>();
}
SimpleIoc.Default.Register<MainViewModel>();
}
public MainViewModel Main
{
get { return SimpleIoc.Default.GetInstance<MainViewModel>(); }
}
}
public class MainViewModel
{
public ObservableCollection<Foo> Foos { get; set; }
public MainViewModel(IDataService dataService)
{
_dataService=dataService;
Foos=_dataService.GetFoos();
}
}
When I resolve my MainViewModel when I call
SimpleIoc.Default.GetInstance<MainViewModel>()
what happens internally is that the SimpleIoc checks to see if the MainViewModel has any dependencies (parameters in its constructor). It then tries to resolve these parameters by looking at the interfaces that have been registered with it. It does this recursively, so if DataService had a dependency it would be instantiated and passed to the DataService constructor when it was being instantiated as well.
Why would I do all this work?
Make your classes easily unit testable
Make your code interface-driven. This means that you're referencing interfaces rather than concrete classes
Make your code loosely coupled. This means that someone can change the implementation of an interface and classes that consume that interface don't care and don't have to be re-coded.
Resolve your classes dependencies in an automated way.
In MVVM Light, you'll see that it can tell when it's running in design-mode (ViewModelBase.IsInDesignModeStatic), this means that you can create design-time services to provide your viewmodels data so your View in Visual Studio contains actual data.
MVVM Light has a lot of nice features but it appears to me that the Service Locator creates unwanted dependency of the views on the view models. Ideally, I would like to have the ViewModelLocator in Library A, the view models in Library B and the views in Library C. Then I can mix and match these as needed for future projects. However, in the design of MVVM Light, as far as I can see, the views (Library C) will always have a dependency on the ViewModelLocator (this is okay) but because the ViewModelLocator (Library A) will always have a dependency on the view models (Library B), then the views will always depend on the view models (this is not okay because a view now must include all the view model libraries it was ever used with across all products).
I believe that Prism gets around this problem by using string keys somehow. Am I missing something?
Oops! I think I just answered my own question. The solution is to make Library A, the ServiceLocator, specific to a particular solution (product). It then contains a reference to the view models only for that solution. Then the views depend on this ServiceLocator which in turn depends on all the view models for that product. The final result is that the views depend only on the views models that it will be used with for that product. There is no problem with thee fact that we are duplicating the ServiceLocator for each solution because this module contains only code that is specific to the solution. The components of the ServiceLocator such as the SimpleIoc class are, of course, common to all solutions, but these have been factored out into reusable classes that we invoke in ServiceLocator.
To summarize things, the problem I am trying to solve is suppose that a solution has 6 view models, four of which are closely related and two of which are closely related. We therefore create two assemblies, each containing the closely related view models. Suppose we design a product that uses one set of view models and the solution is designed to run Windows 8. Now the views are all different and we want to re-use only one set (assembly) of view models. So we just create a new ServiceLocator assembly that points to this assembly of view models and also any others that we need. Our new Windows 8 views now depend on this new ServiceLocator assembly and only the view models that are used in our new product (solution).

ShowDialog a RadWindow with MVVMLight

I have a functional MVVM patterned SL app with a RadWindow (essentially a ChildWindow), that I would like to remove the code-behind in my view that shows the window using its ShowDialog. Both the main view and the window is bound to the same ViewModel if that helps.
The button has both a ViewModel command using a MVVMLight RelayCommand to handle setting state as well as the event handler in the View.
The ultimate solution/pattern will be reused 20+ times so something better than code-behind would be great.
Thoughts?
private void Button_Click(object sender, System.Windows.RoutedEventArgs e)
{
var window = new RadWindowTest.Controls.ChildWindow1();
window.Closed += new System.EventHandler<Telerik.Windows.Controls.WindowClosedEventArgs>(window_Closed);
window.ShowDialog();
}
In this case I would suggest you implement DialogService. This service you can inject into your view model, for testing you will have to inject an instance that does not depend on the view, thus maintaining testability. You can use the ViewModelLocator to make this service available to your application.
Another approach would be to implement a ViewBase class that implements an interface that allows you to display the dialog. This interface is now used by the ViewModel to display a dialog. Again to test you need to provide a different implementation of the interface. A sample can be found here.
Both ideas revolve around the same concept of factoring out the function that shows the dialog. In order to strictly de-couple the View and the ViewModel you will have to think about how the ViewModel specifies which dialog has to be shoen, and how the dialog resut or dialog model is returned to the calling ViewModel.
Which approach is better is open to your judgement. Personally I prefer the first approach as I do not have to inherit the views from a common base class.
PS: Use a command to get to the point in your ViewModel where you want to show the dialog. Using a dialog service should need no code behind.

When should a class use its own getters/setters vs accessing the members directly?

When generating setters and getters in Eclipse one of the options is to use the getters and setters within the class rather than accessing the class members directly. Is this level of class internal encapsulation useful or is it taking a good idea one step too far?
DUPE: Should you use accessor properties from within the class, or just from outside of the class?
I think it's a good idea if you want the potential side-effects to occur - validation, logging etc. (In C# I'd like to be able to declare a variable and property and say that the only access to the variable is through the property.)
Occasionally you may well find you need to set the variable directly precisely because you don't want the side-effects. For instance, you may need to set two variables together, and both the "before" and the "after" states are valid, but setting either property individually would make validation blow up.
It can be useful, if you allow derived classes to re-define your getters. So, using getters even from inside the class will keep your design extensible.
In my opinion this is something that needs to be defined in the coding guidelines.
The short answer is "it depends" :)
Eric Lippert has an excellent article on Automatic vs. Explicit properties that deals with this issue, albeit from a slightly different angle.
Essentially, the question you need to ask is:
"From within the class, [are] the desired semantics of accessing this ... property different from the desired semantics of accessing the property from the outside?"
If the semantics are the same, your class should use its own properties. If the semantics are different, your class will need to directly manipulate the backing fields.
It's useful for example when you have setters which do extra actions like setting a dirty flag or notifying observers.
For getters you may instead of accessing a field compute a value when you change representation.
When you need to extend the getter/setter behavior of a class, it is useful have encapsulated fields (getters/setters instead of direct member access).
Yet in inheritance, it is conceptualy interesting to preserve the inners of your class, if its subclasses shouldn't be aware of its private stuff. So, sometimes the field is private to the implementation of a class, so that even the subclasses aren't aware of it.
I find that I do that at times - specifically when I require, or strongly anticipate that I'll require, some login around getting or setting (and the validation around them) of members.
I find that having private/internal properties does help in these cases.
But I certainly not do it for any memeber.
Latest .NET/VS really helps here as you can declare a property as such:
public string SomeProperty
{
get;
set;
}
and it effectively creates the memebr behind the scene. I know that doesn't help you, but I thought it might be of some interest :-)
If you want for this member to be databindable by either Winform or WPF, I believe that you need to declare it as a property. I'm about 95 percent positive that databinding requires a property (getter/setting syntax). I have a small wpf solution that demonstrates this, but I don't see a way to attach it here.
Here's the code: (built with VS 2008 SP1, targeting .net 3.5 - I used a WPF Project).
There are 2 items in the WPF project, the main window (window1), and the object that we are testing (DataObject)
There is a label on the window that is databound to the Name property in an instance of data object. If you convert the Name property to a field (remove the getter/setter), the databinding will stop working.
Window1.xaml:
<Window x:Class="WpfDatabinding.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Grid>
<Label Name ="Label1" Height="28" Margin="12,24,37,0" VerticalAlignment="Top" Content="{Binding Name}"></Label>
</Grid>
Window1.xaml.cs
using System;
using System.Windows;
namespace WpfDatabinding
{
/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public partial class Window1 : Window
{
private DataObject ADataObject;
public Window1()
{
InitializeComponent();
this.ADataObject = new DataObject();
this.ADataObject.Name = "Hello!";
this.DataContext = this.ADataObject;
}
}
}
namespace WpfDatabinding
{
/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public partial class Window1 : Window
{
private DataObject ADataObject;
public Window1()
{
InitializeComponent();
this.ADataObject = new DataObject();
this.ADataObject.Name = "Hello!";
this.DataContext = this.ADataObject;
}
}
}
DataObject.cs:
namespace WpfDatabinding
{
public class DataObject
{
// convert this to a field, and databinding will stop working
public string Name
{
get;
set;
}
}
}