Caliburn.micro and devexpress: insert tabs (dockpanel) from viewmodel when user clicks - c#

Cheers all,
I'm searching to use the devexpress tool in my visual c# project (vs2013). I'm also using caliburn.micro and i've inserted the Caliburn.Micro.DevExpress reference. So, this is my environment.
The problem: I want create a container, where you can open some predefined tabs. You can navigate in the open tabs, close them and open others.
I'm in stuck with the integration of devexpress and caliburn. Without caliburn and mostly without MVVM pattern, it's easy. But how can I do this using my viewModel?
The result I want is like the example "Simple MDI" in [the official caliburn.micro documentation1]. Instead of the button "open tab", I've my menu in the upper side and, depending on which button is clicked, I want open the relative dockpanel/tab.
Now, in the xaml file, my container is a devexpress object, the "DocumentGroup". My goal is to add dynamically the DocumentPanel(s), like written above.
Is it clear the problem? Some ideas for solution?
UPDATE: in my viewModel I have:
namespace **.ViewModels
{
class MainWindowViewModel : Conductor<IScreen>.Collection.OneActive
{
public void addT() {
Debug.WriteLine("start");
ActivateItem(new ucImpiantiViewModel());
Debug.WriteLine("end");
}
}
}
And in the xaml I have:
...
<dxd:DocumentGroup x:Name="Items" ItemHeight="3*" SelectedTabIndex="0">
...
I thought this way was good, but still nothing.. the good new is only that the console.writeline are working!

Related

Prism WPF: How to Open A New Window/Dialog

When using code behind, the code looks like this:
AnotherWindow x = new AnotherWindow();
x.Show() ;
// or x.ShowDialog()
But how can I achieve this using MVVM? Specifically Prism?
In case you need to build a dialog for asking user login input or progressing dialog, MahApps.Metro can be a useful toolkit as it provides you with some built-in dialog UI/functionalities with MVVM pattern. For more information, check some examples here:
https://mahapps.com/controls/dialogs.html
In Prism, there's the InteractionRequest for short-lived dialogs. If you're looking for a long living dialog, like a second application window or shell, you're stuck with new Window ... Show.
To make your dialog service mvvm-friendly, you should hide it behind an interface and make it as generic as possible. Using view model first here eliminates the need to specify a window type, because you can provide a default window that just contains one large ContentControl, and the view can be mapped as DataTemplate.

Opening a second Window from MainWindow following MVVM and loose coupling

At first: This App and Question is for learning purpose
I'm on a new application and facing the problem that I want to open a Window when the user clicks on a Button in the MainView. In the past I'd have designed a Command which just creates the new Window and displays it
new RelayCommand((x)=>new SecondWindow().Show());
Now with this new Project I'm trying to fully decouple all classes from each other. To achieve this my App consists of 4 Assemblies (BL, COM, DAL and UI).
As in each WPF Application, the App starts with the MainWindow.xaml. The MainWindow.cs will create it's instance of MainWindowViewModel:
public ViewModel VM {get; private set;}
public class MainWindow(){
VM = new ViewModel();
InitializeComponent();
}
(which already violates loose coupling) (Any tips on how to make it better?)
My last attempt is to create an instance of my second Window inside my main window
<Window.Resources>
<local:SecondWindow x:Key="sw"/>
</Window.Resources>
and pass it as a CommandParameter to my Command
CommandParameter="{StaticResource sw}"/>
new RelayCommand((x)=> ((Window)x).Show());
This solution works but has one big disadvantage - the second window get's created immediately after the app starts - and so does it's ViewModel which starts some heavy processes (DB Connections etc.)
I've heard something abour IoC principle but I really don't know how to use it with an wpf application.
You are thinking along the right lines.... you basically have to create a List of ViewModels as your application starts up, then you can switch between them as the user presses buttons and pass the name of the ViewModel as a CommandParameter to your Command handler....
You might find this link to Rachel Lim's Blog
https://rachel53461.wordpress.com/2011/12/18/navigation-with-mvvm-2/
Also, I'm not going to post any code here coz it simply gets too complicated. So here is a download to just about the simplest example I could come up with
http://www.mediafire.com/download/3bubiq7s6xw7i73/Navigation1.rar
Download and un-RAR it (with win RAR) You will need to step though the code, figure out what its doing and how its doing it then modify it to suit your needs... Or modify your needs to suit the code.....
The example is a modification of Rachel Lim example. It simply contains Views and ViewModels, there are no Models or data. It demonstrates switching between two different Views.
UPDATE 1
With specific reference to the demo code.... Your VMs are added to a static collection of VMs (see AddViewModel function), each View ( the DataTemplate associates View with ViewModel) is selected when you click a button for example, by calling 'SelectViewCommand' which in turn sets Current_ViewModel to the selected ViewModel... the corrisponding ContentControl is then updated to display that currently selected View...
I know is confusing and very difficult to explain
When you press a button to 'change Views' you are actually changing the value of the property that your ContentControl is bound to, so you have to call the correct SelectViewCommand in the SAME instance of the class that your ContentControl is bound too...
In the demo you'll see that in the 'LogOn_View' I call
Command="{Binding DataContext.SelectViewCommand, ElementName=Base_V}"CommandParameter="Main_ViewModel"
Here I am calling the SelectViewCommand in the Base_ViewModel (x:Name="Base_V" in Base_View XAML), That's because I want to change the View that is displayed in the Base_View's 'ContentControl'
In Main_View I call
Command="{Binding SelectViewCommand}" CommandParameter="MainV1_ViewModel"
Here I am calling the SelectViewCommand in the Main_ViewModel, That's because I want to change the View displayed in the MainView's 'ContentControl'....
I typically create a WindowService class for managing window changes/dialogs in MVVM. Having "View" code in the ViewModel (i.e. Window.Show()) goes against MVVM principles. For example:
public class WindowService : IWindowService
{
public void ShowDialog<T>(ViewModelBase viewModel) where T : IApplicationDialog
{
IApplicationDialog dialog = (IApplicationDialog)Activator.CreateInstance(typeof(T));
dialog.Show();
}
}
And then your call from the ViewModel would look something like:
windowService.ShowDialog<SecondWindow>(new SecondWindowViewModel());
If you're using DI, you can pass a reference to the IoC container to the window service and create the window instances from that rather than using Activator.CreateInstance (i prefer the DI approach personally)

WPF, MVVM, and effective navigation / control flow

I am currently building an application based on a real world scenario, to help me learn and understand WPF and MVVM. To that end I have read and worked through Karl Shifflett's "In The Box" VSIX, and I was able to adapt most of the concepts to the application that I am working on.
While I think MVVM is a powerful design pattern, it does (seemingly) make things that were once trivial (e.g. displaying messages, navigation, interacting with multiple window), not so trivial or straightforward. Now onto the crux of my problem / confusion.
The WPF application that I am working on is a Windows based application, and I am working from a set of basic requirements:
A basic login screen
After a successful login, close the login screen and open the actual application
Simulate a typical program workflow (opening "child" windows via button clicks, displaying modal windows, etc.)
Preform data validation / error handling
Log out
I am used to working with MDI Applications on a windows platform where interactions on a parent form cause child forms to open; I understand that MDI is not something that WPF supports and I am fine with approaching development from a different perspective. My UI would still work in a similar manner to a MDI application though: I have my application layout, and as I interact with that layout my application will respond by opening windows, displaying messages, and so on. It isn't clear to me (via MVVM) how to interact with multiple windows, or how well MVVM would scale to a large application with many windows / views.
I am not opposed to using something like Prism, but I haven't found a good article on how Prism approaches my particular problem very well. Any help, advice, feedback, or otherwise is greatly appreciated!
Have you tried looking at nRoute Framework?
A link can be found here
There are actually some good tuturials about prism
Link 1
Link 2 (Part II of Link1)
Link 3
For a more straight forrward application (not very complex and modular), you can always create a aplication, with a main window that manages child usercontrols (login window, menu window, other windows ...)
For example, create a window a contentpresenter in it, and in codebehind:
public partial class ShellWindow: Window
{
public enum PagesTypes { Login, Home }
PagesTypes currentOpenedPage;
LoginUserControl login;
HomeUserControl home;
public WindowController()
{
InitializeComponent();
login = new LoginUserControl ();
login.GoToPage += new LoginUserControl.ChangePageHandler(GoToPage);
GoToPage(PagesTypes.Login);
}
public void GoToPage(PagesTypes page)
{
switch (page)
{
case PagesTypes.Login:
//Close last opened usercontrol,
....
//open new usercontrol
login = new LoginUserControl();
contentpresenter.content = login;
break;
//other pages cases
....
}
currentOpenedPage = page;
}
}
And in for example the login usercontrol:
public partial class LoginUserControl : UserControl
{
internal delegate void ChangePageHandler(ShellWindow.PagesTypes toPage);
internal event ChangePageHandler GoToPage;
public LoginUserControl()
{...}
//Methods for login
.....
internal void LoginOK()
{
if(this.GoToPage != null)
GoToPage(ShellWindow.PagesTypes.Home);
}
}
You can build a good dynamic using this method changing usercontrols, simulating diferent windows.
Hope this gives you some ideas.
MVVMing your child windows actually can be kind of easy, especially if you decide that a tabbed interface is OK. Your outer window's view model simply has a collection of ChildWindowViewModel. You create a new tab just by creating the new view model, asking the outer window to add it to it's collection, and WPF's DataTemplate awesomeness will take care of the proper display. You'll have to do some fiddling to get tab 'close' operations working the way you want. It's kind of a pain but doable.
If you really want to do MDI, there's nothing built into WPF for it (I think Microsoft has decided that it is a bad UI pattern now?), but there may be 3rd party controls out there for it. Any good one will still mirror this solution where their MDI container control will bind to your list of child window view models.

Calling a method from Usercontrol xaml.cs to View Model

I am using MVVM in my project and I am implementing the Diagram Designer and I am using RAD Diagram control of Telerik.I am dragging the shape from my RadToolBox to canvas for which I have implemented the event.Now on this event I want to save the diagram in RavenDB once the shape has been dropped on Canvas ( Ruler).This whole thing is in the User control stored in one library and I am creating the reference of this library in my actual WPF form which is in other library.My requirement is I want to call the Save command which is present in View Model of WPF form, from my xaml.cs of the user control and this user control is present in other library.
How shall i achieve the same.Please help.
Why do have multiple assemblies? If you don't need them, then make your life simpler and just use NameSpaces to separate your controls from your forms in the same assembly.
Right now that's said :-)
The easy way is via an Event. Add an event to your UserControl, and then in the Window add the code when the event happens.
Have a read through MSDN Events
I really dont Why you would need to call a save command from another WindowsForm.
Telerik UI Diagram provides indefined save Command which is used to save the Diagram,
InXAML,
<Grid.CommandBindings>
<CommandBinding Command="telerik:DiagramCommands.Save" Executed="ExecuteSave" />
</Grid.CommandBindings>
And In code behind define save function,
private void ExecuteSave(object sender, ExecutedRoutedEventArgs e)
{
e.Handled = true;
this.diagram.save();
}

Change selected tab from ViewModel And send objects between ViewModels

I got a wpf desktop application with 3 ViewModels.
I have 1 ViewModel that contains a tabhost and tabs. And I got 2 tabs. Each of those tabs has it's own ViewModel.
The problem I have is that in tab1 I have a listview with searchresults and a button. When I select one item in that list and press the button, I want to change tab and display information about that item I selected in tab2.
I have searched for a solution, but it seems to include creating all ViewModels in the MainViewModel and providing a reference of the MainViewModel to all the subViewModels.
Is there no other way?
EDIT
I just managed to solve my problems with MVVM light that I added to the project.
By binding a method in the MainViewModel and a property in it to the .xaml I can now call it from tab1 with info to tell it to change tab.
Also, by binding a method in tab2 I can now send over an item from tab1 in the same manner.
This is how I solved it after importing MVVM light into the project.
In tab1
Messenger.Default.Send<string, tab2ViewModel>(--object to send to tab2--);
Messenger.Default.Send<int, MainViewModel>(--tab index--);
In Main/tab2
Messenger.Default.Register<int>(this, ChangeTab);
public void ChangeTab(int i)
{
SelectedTabIndex = i; //Bound property in .xaml
}
It seems to automagically just work..
P.s. Thanx for reply. I shall look into how Prism work as well, and see if there is any advantages to use that instead of MVVM light(Not right now however).
A good solution to your problem would be to use the EventAggregator of Prism.
This service lets you listen to and publish a particular type of event from anywhere in your application without tying your view-models to each other. This is a really nice solution for MVVM and other losely-coupled designs. It is easy and works like a charm.
You can find the documentation here : EventAggregator
More information about Prism here : Prism on Codeplex
Here is a concrete sample. Imagine you want to change the title of the main Window from anywhere in the application. You would create this event:
public class TitleChangedEvent : CompositePresentationEvent<string>{}
Then you would suscribe to this event in your MainWindowViewModel like this:
eventAggregator.GetEvent<TitleChangedEvent.Suscribe(
(newTitle) =>
{
this.WindowTitle = newTitle;
});
And finally you can update the title from anywhere in your application like this:
eventAggregator.GetEvent<TitleChangedEvent>().Publish("This is a new title!");
Quite easy as you can see.
Smililarly with MVVM Light you would first create a message for notification:
public class TitleChangedMessage : GenericMessage<string>{}
Then you would listen to the message like this in your MainWindowViewModel:
Messenger.Register<TitleChangedMessage>(this,
(message) =>
{
this.WindowTitle = message.Content;
}
And you would send an update like this:
Messenger.Send<TitleChangedMessage>(this, new TitleChangedMessage("This is a new title!"));
This is the MVVM Light way to do it :)
You can also have a look at this related question: Messenger class in MVVM Light

Categories

Resources