communication between user controls - winforms

I have a windows form that has two usercontrols, UC1 and UC2. UC2 need some information about the state of UC1. One way I can think of is that UC2 has an instance of UC1 as class member and I can initialize that instance of UC1 (contained in UC2) with the one contained in form. After that whenever UC2 need to get any info about UC1, it can just get that from its local class variables. Not sure though if its the best approach?

Just create some object that has two interfaces. One to shove stuff in and one to receive stuff from. The object itself will just shove straight through. The the owner form creates an instance and assigns the injects the interfaces into UC1 and UC2.
If the owning form doesn't need to "pair" them up, then just use static instance.

Related

WPF+Unity: UserControl with usage of services?

I've an UserControl, which basically looks like this:
You guessed, the goal is to allow the user to choose a file/folder when clicking on Browseand then display the file path in the TextBox.
I started my first fully MVVM application(Using Prism+Unity), and I have in fact an IDialogService which allows me to show a MessageBox, but also display some OpenFileDialog and SaveFileDialog.
I would like to use the implementation provided for this IDialogService in order to display to the user my dialog box once the Browse command is executed.
Since the UserControl isn't built with Unity, how to request the implementation ?
If I understand you correctly, your UserControl needs to get hold of the Unity container you're using, one way or another. If you're instantiating the UserControl yourself, you can consider adding it as a constructor parameter; if it's instantiated by the framework you could consider a Container property or a setter method. Or you could go with the container as a singleton.
Either way, assuming your UserControl has a field like so...
IUnityContainer container;
...and that you've managed to point it to the container you're using, you should be able to resolve your service the normal way:
IDialogService service = container.Resolve<IDialogService>();
service.OpenFileDialog(...);

Accessing ViewModel data in View

I just want to ask if it's OK to access the ViewModel's data in the View backend?
Basically I just need a check to see if a ViewModel's property is set (which gets set when the user selects something), and if it's not I'll just redirect the user to another View telling him he needs to select something first. Is this a poor-design practice or is it OK, just for a minor check like this? Really don't want to implement a static class and extrapolate the data to it, and check it instead.
Another question tightly related to this, is can I call a method from the View (when the View is closing), that unregisters that particular ViewModel from the IoC container (this ViewModel isn't singleton). The alternative is to send a message from the View to the ViewModel when the View is closing, and when the ViewModel gets that message it unregisters itself. The problem I'm trying to solve with this is that, every time that ViewModel is requested it has to be a new one, but my IoC container caches them, making my program a memory hog. All of the ViewModels get released on application exit, meaning x ViewModels will still exist in the cache even though they're most likely not needed.
Basically I just need a check to see if a ViewModel's property is set (which gets set when the user selects something), and if it's not I'll just redirect the user to another View telling him he needs to select something first. Is this a poor-design practice or is it OK, just for a minor check like this?
It does not seem to be wrong to check the value of some ViewModel property and reflect the changes on the View side. The View state could be "bound" to the ViewModel state by the WPF data binding mechanism: Binding, Triggers (Trigger, DataTrigger, EventTrigger), Commands (including EventToCommand), etc.
But sometimes it is useful to handle ViewModel state change by the ViewModel itself using UI Services. For example, IWindowService interface can be introduced to allow to open windows from the context of the ViewModel implementation.
Another question tightly related to this, is can I call a method from the View (when the View is closing), that unregisters that particular ViewModel from the IoC container (this ViewModel isn't singleton).
...
The problem I'm trying to solve with this is that, every time that ViewModel is requested it has to be a new one, but my IoC container caches them, making my program a memory hog. All of the ViewModels get released on application exit, meaning x ViewModels will still exist in the cache even though they're most likely not needed.
It seems to be strange that the described dependency container "cache effect" exists when the registration is specified as "resolve per call behavior" (not "singleton behavior"). Please check that the registration is specified as "resolve per call behavior" (for example, PerResolveLifetimeManager in terms of Unity Container Lifetime Managers).
Update
The ViewModel lifetime problem exists because SimpleIoC container is used.
I would like to recommend using another dependency injection container (with appropriate lifetime management) to make the implementation less complex and error-prone.
But, if there is a strong need to use SimpleIoC container, some kind of the ViewModel lifetime management can be implemented using:
SimpleIoc.Default.GetInstance<ViewModel>(key); method call to resolve an instance of ViewModel;
SimpleIoc.Default.Unregister(key); to un-register the instance when it is no longer needed (Closed event, etc).
The implementation can be found here: answer #1, answer #2.

In loaded event of user control, the other user control's control is null in WPF

I have user control, let say UC1.
Inside UC1, I have three more user controls, let say UC2, UC3 and UC4.
The issue is when I refer UC2's control from UC4 loaded event, the UC2's referred control is null.
Is it possible? Since the order of creation of User controls will be UC1, UC2, UC3 and UC4.
Technically when I am referring from loaded event of UC4, all the controls in UC2 should have been created. But in my case it is null.
Any ideas?
The problem may be related to the instance because while checking if you have created another instance
like this to check its content.
In UC4 :
UC2 obj_uc2 = new UC2();
Then it will give you null because its a new instance. For this you have to get the instance which is alive.

Should I dependency inject? How do I do it?

Okay, so I am working with Microsoft Prism in WPF using a MVVMC(or MVCVM) pattern.
In my ChatModule I have a series of Views, ViewModels, and one Controller.
For the Views I have
ChatAreaView - Displays the chat messages that come in to be read. This is hosted inside of a TabControl region so that I can have chat windows between the user and other users, or maybe file transfer windows, etc.
UserAreaView - This is a list of the users. Right clicking has context menu to interact with them... like sending a file or whispering.
MessageAreaView - This is where the user types in messages to be sent to all of the others.
For each view, I have a corresponding ViewModel. ChatAreaViewModel, UserAreaViewModel and MessageAreaViewModel. These ViewModels essentially only contain properties.
For example, the UserAreaViewModel defines a struct of type User which is essentially just a Name. Actually this is defined outside of the class, but still... it uses it. It has an ObservableCollection to store a list of all the Users who are currently connected. It also has ICommand properties defined to interact with the user. Right now I have SendFile, Whisper and Nudge... with intent on adding more in the future.
The Controller creates these views and ViewModels, and marriages them. It news them up, assigns the ViewModel as the corresponding View's DataContext, and sets all the initial properties of the ViewModel. Over the lifetime of the module, it will react to user interaction and execute DelegateCommands that it has assigned to each of the ViewModel's ICommand properties. These will further alter the state of the properties in a ViewModel.
I am using the actual types of Views and ViewModels, instead of interfaces, like such.
#region Views
ChatAreaView viewChatArea;
UserListView viewUserArea;
MessageView viewMessageArea;
LoginPromptView viewLoginPrompt;
#endregion
#region ViewModels
ChatAreaViewModel viewModelChatArea;
UserAreaViewModel viewModelUserArea;
MessageAreaViewModel viewModelMessageArea;
LoginPromptViewModel viewModelLoginPrompt;
#endregion
Would things be a lot more neat, less coupled if I defined interfaces for the Views and ViewModels, and operated on these interfaces within the controller instead of the concrete implementations? Could I then just register them with my Container in the Module class(which is essentially the root of each Module)?
What do I have to gain from doing this? How would I implement an interface for each view to distinguish them from the others? They don't really do ANYTHING except have XAML... and teh ViewModel's don't really do anything either except have certain properties. And those properties might be subject to change. On the UserAreaViewModel for instance, I will definitely want to add more commands so a user can interact with another user in different ways.
Can somebody help me out here? In my mind I'm thinking I should be abstracting this stuff, but I don't really know a logical way I should be going about it, or even if it's a wise idea to do so. What do I have to gain?
Thank you for your time. The below image is an example of what I'm working on. Ignore the Add new Item button and the styling of everything... that's not what I'm working on right now.
loosely coupled - can replace an entire class with altogether different implementation in future.
independent development.. can inject a dummy UI / view until final UI gets ready. two pieces can evolve at the same time (after having a common contract).
no need to add references to the modules (implementing the view). can use ConfigurationModuleCatalog to discover types from config file.

Silverlight: Add same UserControl to more than one Canvas

I have a bunch of UserControls ('MyUserControl') that I want to have a user manually add to one or more Canvases. One instance of a UserControl cannot be a child element of more than one container (otherwise a 'System.InvalidOperationException: Element is already the child of another element.' is thrown).
Is there a way to do this without creating new (duplicate) instances of the MyUserControls? If not, what would be the best strategy to keep duplicate instances of the MyUserControls in sync?
You cannot add the same instance of a control (any control) as a child of more than one parent. You will need to create multiple instances of your Usercontrol and place each on its own parent.
If you need to keep the data they display in sync then you should store that data in an object separate from the user controls themselves, its this object that you would only have one instance of. Typically you would assign this data object to the DataContext property of each user control, then the various component parts of the User control can get their data using data binding.
If you ensure that your data object implements INotifyPropertyChanged correctly then when one User control makes a change to the data it will be reflected in all the other User Controls referencing the same data object.

Resources