I am using roslynpad project for educational purposes.
It is based on avalon dock library which implements MVVM pattern which is new to me.
There are editors window's which can be docked. I want to add new window that could be docked also but it should be my custom window.
I see that dock manager binds to collection of OpenDocumentViewModel objects. OpenDocumentViewModel represents the model of the view as is understand.
Than there is a DocumentView class which describes a layout of the window.
Now there is a line in main window xaml file:
<DataTemplate DataType="{x:Type ui:OpenDocumentViewModel}">
<roslynPad:DocumentView />
</DataTemplate>
This line is responsible for connecting view model and document view, in other words says that for that DocumentView design should be attached to windows in OpenDocumentViewModel collection.
I want to insert my window with my own design. So for particular window i would like to write
<DataTemplate DataType="{x:Type ui:OpenDocumentViewModel}">
<MyCustomView />
</DataTemplate>
But i don't know how to do that or maybe it is impossible?
Related
I'm developing an application with one main window and few more windows like ProjectProperties window, UsersData window etc. I want these windows to be created only once (for example at application start) and just hide/unhide them when needed. They will be disposed only when application is closed. Where should I keep the instances of these windows? Should I keep their ViewModels instances in the MainWindowViewModel class? What about the Views (keep them in MainWindowView)? How do I hide/unhide them?
I don't want to use WVVM Light, Calibrum etc. Just pure MVVM.
I'm new to WPF and MVVM so please be specific as much as possible.
This link has a good toturial about navigation (i think that is what you want) with pure MVVM.
https://rachel53461.wordpress.com/2011/12/18/navigation-with-mvvm-2/
Where the views are "stored", is in here:
<Window.Resources>
<DataTemplate DataType="{x:Type local:HomeViewModel}">
<local:HomeView />
</DataTemplate>
<DataTemplate DataType="{x:Type local:ProductsViewModel}">
<local:ProductsView />
</DataTemplate>
</Window.Resources>
That is also the relation between Views and ViewModels.
EDIT: As your new to MVVM, i also advise you to read this one https://rachel53461.wordpress.com/2011/05/08/simplemvvmexample/
Hope it helps.
I have a Window, and there are three types of content that can be displayed (they are all of UserControl type):
Login view
App view
Error reporting
What's the most appropriate way to switch between these? My thought was to pass instance of Window in the constructor and then addressing it's content.
Content = new LoginView(this);
And then change the content from LoginView,
public LoginView(Window wnd){
InitializeComponents();
wnd.Content = new MainView(wnd);
}
But this wouldn't update the Window's content. Is it caused by the caller (LoginView) being the window's current content? If that's the case, what would be the proper way to handle such situation?
Also note that the snippet provided doesn't include any logic. I just left it as simple as required to demonstrate the issue I'm facing.
Basically the connection between those controls is such:
Login view
- when the application starts
- when the application window sends a request (to the server) that returns unauthorized
App view
- handles all the application's features
Error view
- replaces app/login view in case of an error and informs user about what to do
You should maybe look at the MVVM pattern. Usually every user control / view should have its own view model, when using the MVVM pattern. So you can define different Views inside a MainView. Like the following example shows:
<Window.Resources>
<DataTemplate x:Key="LoginView" DataType="{x:Type ViewModel:LoginViewModel}">
<local:LoginView />
</DataTemplate>
<DataTemplate x:Key="AppView" DataType="{x:Type ViewModel:AppViewModel}">
<local:AppView />
</DataTemplate>
<Window.Resources>
So in your code of the MainView, you have to pass the appropriate ViewModel in a ContentControl. This will reference the right View.
<ContentControl Content="{Binding LoginViewModel}" />
So the DataTemplate will be shown, depending on the xxxViewModel that is passed.
I am currently writing a desktop application, but I cannot seem to get my head around what to use when redirecting someone to a new section of the application.
My options appear to be
Window
Page
UserControl
but I don't understand what the difference between them is, and when I should use each one.
Could someone explain the differences for me, and give an example of what situations/applications you may use each one for?
A Window object is just what it sounds like: its a new Window for your application. You should use it when you want to pop up an entirely new window. I don't often use more than one Window in WPF because I prefer to put dynamic content in my main Window that changes based on user action.
A Page is a page inside your Window. It is mostly used for web-based systems like an XBAP, where you have a single browser window and different pages can be hosted in that window. It can also be used in Navigation Applications like sellmeadog said.
A UserControl is a reusable user-created control that you can add to your UI the same way you would add any other control. Usually I create a UserControl when I want to build in some custom functionality (for example, a CalendarControl), or when I have a large amount of related XAML code, such as a View when using the MVVM design pattern.
When navigating between windows, you could simply create a new Window object and show it
var NewWindow = new MyWindow();
newWindow.Show();
but like I said at the beginning of this answer, I prefer not to manage multiple windows if possible.
My preferred method of navigation is to create some dynamic content area using a ContentControl, and populate that with a UserControl containing whatever the current view is.
<Window x:Class="MyNamespace.MainWindow" ...>
<DockPanel>
<ContentControl x:Name="ContentArea" />
</DockPanel>
</Window>
and in your navigate event you can simply set it using
ContentArea.Content = new MyUserControl();
But if you're working with WPF, I'd highly recommend the MVVM design pattern. I have a very basic example on my blog that illustrates how you'd navigate using MVVM, using this pattern:
<Window x:Class="SimpleMVVMExample.ApplicationView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:SimpleMVVMExample"
Title="Simple MVVM Example" Height="350" Width="525">
<Window.Resources>
<DataTemplate DataType="{x:Type local:HomeViewModel}">
<local:HomeView /> <!-- This is a UserControl -->
</DataTemplate>
<DataTemplate DataType="{x:Type local:ProductsViewModel}">
<local:ProductsView /> <!-- This is a UserControl -->
</DataTemplate>
</Window.Resources>
<DockPanel>
<!-- Navigation Buttons -->
<Border DockPanel.Dock="Left" BorderBrush="Black"
BorderThickness="0,0,1,0">
<ItemsControl ItemsSource="{Binding PageViewModels}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Content="{Binding Name}"
Command="{Binding DataContext.ChangePageCommand,
RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
CommandParameter="{Binding }"
Margin="2,5"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Border>
<!-- Content Area -->
<ContentControl Content="{Binding CurrentPageViewModel}" />
</DockPanel>
</Window>
Window is like Windows.Forms.Form, so just a new window
Page is, according to online documentation:
Encapsulates a page of content that can be navigated to
and hosted by Windows Internet Explorer, NavigationWindow, and Frame.
So you basically use this if going you visualize some HTML content
UserControl is for cases when you want to create some reusable component (but not standalone one) to use it in multiple different Windows
All depends on the app you're trying to build. Use Windows if you're building a dialog based app. Use Pages if you're building a navigation based app. UserControls will be useful regardless of the direction you go as you can use them in both Windows and Pages.
A good place to start exploring is here: http://windowsclient.net/learn
We usually use One Main Window for the application and other windows can be used in situations like when you need popups because instead of using popup controls in XAML which are not visible we can use a Window that is visible at design time so that'll be easy to work with
on the other hand we use many pages to navigate from one screen to another like User management screen to Order Screen etc In the main Window we can use Frame control for navigation like below
XAML
<Frame Name="mainWinFrame" NavigationUIVisibility="Hidden" ButtonBase.Click="mainWinFrame_Click">
</Frame>
C#
private void mainWinFrame_Click(object sender, RoutedEventArgs e)
{
try
{
if (e.OriginalSource is Button)
{
Button btn = (Button)e.OriginalSource;
if ((btn.CommandParameter != null) && (btn.CommandParameter.Equals("Order")))
{
mainWinFrame.Navigate(OrderPage);
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error");
}
}
That's one way of doing it We can also use a Tab Control instead of Fram and Add pages to it using a Dictionary while adding new page check if the control already exists then only navigate otherwise add and navigate. I hope that'll help someone
Most of all has posted correct answer. I would like to add few links, so that you can refer to them and have clear and better ideas about the same:
UserControl:
http://msdn.microsoft.com/en-IN/library/a6h7e207(v=vs.71).aspx
The difference between page and window with respect to WPF:
Page vs Window in WPF?
This MVVM stuff is making my head hurt. I have an application which has a list of editors in a left pane. On the right is a tab control where the editors will be displayed. I have a main application view model that contains a collection of view models. I call this collection Workspaces. This is borrowed from the MvvmDemoApp that Microsoft provides here.
public ObservableCollection<WorkspaceViewModel> Workspaces
{
get
{
...
}
}
These workspaces are bound to a tab control in the main application window like so:
<DataTemplate x:Key "WorkspacesTemplate">
<TabControl
IsSynchonizedWithCurrentItem="True"
ItemSource="{Binding Workspaces}"
SelectedItem="{Binding ActiveWorkspace}"/>
</DataTemplate>
...
<ContentControl
Content="{Binding}"
ContentTemplate="{StaticResource WorkspacesTemplate}"/>
The view models are tied to a view using DataTemplates like so:
<DataTemplate DataType="{x:Type vm:MessageLogViewModel}">
<vw:MessageLogView/>
</DataTemplate>
This works fine. However, now I need to make the application configurable where the list of editors are read from a config file. I imagine this config file will contain the view and view model components for each editor. But, how do I tie the two together so that when someone binds to a view model (or a collection of view models), the correct view gets displayed (similar to what the DataTemplate does but in code, not XAML)?
I'm trying to stay away for Inversion of Control (IoC) techniques. I'm not sure our team is ready for that must sophistication.
IoC is the perfect solution for this however without this option you could creating the XAML data template in the view model using an XmlWriter and expose it as a property to bind to.
Edit: Bindings
You have your list of view models. Create and expose this XamlTemplate property in each view model (in a base view model class). The property should create Xaml along the lines of:
<DataTemplate xmlns:vw="...">
<vw:MessageLogView/>
</DataTemplate>
Then use a ContentControl to bind to:
<ContentControl Content="{Binding ViewModel}"
ContentTemplate="{Binding ViewModel.XamlTemplate}" />
I using from mvvm in my application. I want know how to define my user control in mvvm pattern.
Must I define it by using from mvvm, or I can define it generally?
Let's just call the control that embeds the user control MainWindow, and the user control UserControl. Since you are in MVVM pattern, you have at least one View Model for the outer view - I usually use the name MainVm.
You have two choices for the user control: They can share the same View Model, or you could have a sub view model, just for the UserControl, i.e. UserVm.
For your first choice, you do nothing. You define UserControl (Visual Studio 'add new item' -> User Control is a pretty good start). Then, you simply embed it in Main Window.
<Window
x:Class="SO.MainWindow"
...
xmlns:src="clr-namespace:SO"
...
>
...
<src:UserControl />
...
</Window>
UserControl will inherit the same DataContext from MainWindow, and do all the {Binding} as you would do in the MainWindow.
If you want to have a sub view model (UserVm) - it would typically be a public property of the MainVm (say, userVm). In that case, you'll set the DataContext of the UserControl when you reference it.
<src:UserControl DataContext="{Binding Path=userVm}" />
Another popular paradigm would be to declare the DataTemplate instead of the UserControl. If you do that, you just need to put the UserVm (either instantiate it in the XAML, or through binding):
<Window x:Class="MainWindow" ...>
<Window.Resources>
<DataTemplate x:Key="UserDt"> <!-- or user TargetType instead of x:Key -->
...
</DataTemplate>
</Window.Resources>
...
<!-- You can put in a ContentControl like here: -->
<ContentControl Content="{Binding Path=userVm}"
ContentTemplate="{StaticResource UserDt}" />
<!-- or, if you defined TargetType for the DT, you can simply instantiate
the sub VM here. I don't like this apporach but it exists. -->
<src:UserVm />
</Window>
I think that depends on the user control. The user control can be just a view, in which case you would compose a larger control or page which has this user control as part of the whole. The larger control or page would provide the view and the view model parts for this view.
Or you could create a self contained user control which has all of mvvm and use events to interact with the larger user control that it is a part of.
I suspect you'll get better reuse and modularisation with the second approach.
In short: it depends.