Open WPF Window in StackPanel [duplicate] - c#

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?

Related

How to bind data in XAML programmatically

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?

How do I tab between text boxes on a form in C#?

I'm trying to get the functionality to tab to the next text box once the user has input their data for the previous text box. For example, once they filled in a company name I'd like to be able to hit Tab and set the focus on the next text box "Job Name". Is this done in the code or the form properties?
Here is some of my code. I'm unsure how to nest a KeyEventsArgs within these, which is how I've seen others set the focus to the next text boxes using the KeyPress function.
private void textBox1_TextChanged(object sender, EventArgs e)
{
CompanyName = textBox1.Text;
textBox1.AcceptsTab = true;
}
private void textBox2_TextChanged(object sender, EventArgs e)
{
JobName = textBox2.Text;
textBox2.AcceptsTab = true;
}
From the question you've asked and the code sample provided, there seems to be somewhat of a disconnect between your approach and the desired functionality.
As you would like the user to be able to use the Tab key in order to shift keyboard focus between elements in the window, you need only provide a TabIndex attribute on each of your TextBox controls. There is no need to use the TextChanged events to achieve this and it can be done completely in XAML for simplicity's sake.
From how I interpret your question, your next follow-on will likely be:
How do I initially give focus to a control when the application
starts?
To address this, there are a couple of alternatives available, simplest of which comes in the form of the FocusManager, which again I've illustrated usage of in XAML.
For convenience, here is a XAML-only implementation with TabIndex and FocusManager implemented:
<Window x:Class="tab_navigation.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:tab_navigation"
mc:Ignorable="d"
Title="MainWindow" ResizeMode="NoResize" SizeToContent="WidthAndHeight" FocusManager.FocusedElement="{Binding ElementName=TbxCompanyName}">
<Grid Margin="10">
<StackPanel Orientation="Vertical">
<StackPanel Orientation="Vertical" Margin="0,0,0,10">
<Label Content="Company Name:" Target="{Binding ElementName=TbxCompanyName}" />
<TextBox Name="TbxCompanyName" TabIndex="0" Width="160" HorizontalAlignment="Left"/>
</StackPanel>
<StackPanel Orientation="Vertical">
<Label Content="Job Description:" Target="{Binding ElementName=TbxJobDescription}"/>
<TextBox Name="TbxJobDescription" TabIndex="1" Width="160" HorizontalAlignment="Left"/>
</StackPanel>
</StackPanel>
</Grid>
Give me a shout if you need any further help, although I would strongly recommend checking out some of the MSDN resources first, particularly those concerning Focus
UPDATE: In response to comment regarding implementing the solution,
WPF has a different design and best practices from that of WinForms.
I would strongly make the case that you cease using Forms and instead use a Window or UserControl derived class in place of a Form in your WPF project unless there is a very, very good reason for doing so. If you continue to use a Form inside of your WPF project, you will indeed need to implement your own keyboard navigation logic inside that form, and bridge various other gaps you'll inevitably run into when trying to get a Form behave in a commonly acceptable way.
I'll instead show you how you can achieve your request using an objectively better and more suitable approach in WPF-only, using Window or UserControl elements. There is also a complete solution zip downloadable here.
WPF is by design a lot more modular than WinForms and splits the areas of concerns nicely by default, although most developers implement a design pattern ontop of this; MVVM is the current darling of WPF, and does add quite a lot of value to a project, although it is outside the scope of your question, so I shall instead address the question itself on the grounds of how to achieve the request in its most basic forms. Do please be aware though that this is not the entirely ideal solution and I would strongly recommend you learn and implement the MVVM pattern for WPF if you are not already familiar with it.
With that disclaimer out of the way, instead of using a Form in WPF, its more useful for us to make a class which derives from Window. An even more common scenario in WPF would be that you would want to have a single window whose content changes between different views, rather than say creating multiple windows, although again that is outside the scope of the question and would rely upon reading into Binding and MVVM. I'm going to be showing you a quick and easy way to get the functionality you've asked for, I'm just trying to iterate here that this is not the norm almost all of the time.
To make a working solution, do the following to your project:
Right click your project in the solution explorer (presuming you are using Visual Studio)
'Add' a 'New Item...'.
Choose the 'Window (WPF)' template and name it. I'm going to call it CustomerInformationEntry from here out.
Open the CustomerInformationEntry.xaml file that has been created for us, remove the <Grid></Grid> tags and copy/paste this excerpt from the XAML I've already provided from above in their place:
<Grid Margin="10">
<StackPanel Orientation="Vertical">
<StackPanel Orientation="Vertical" Margin="0,0,0,10">
<Label Content="Company Name:" Target="{Binding ElementName=TbxCompanyName}" />
<TextBox Name="TbxCompanyName" TabIndex="0" Width="160" HorizontalAlignment="Left"/>
</StackPanel>
<StackPanel Orientation="Vertical">
<Label Content="Job Description:" Target="{Binding ElementName=TbxJobDescription}"/>
<TextBox Name="TbxJobDescription" TabIndex="1" Width="160" HorizontalAlignment="Left"/>
</StackPanel>
</StackPanel>
</Grid>
Add FocusManager.FocusedElement="{Binding ElementName=TbxCompanyName} to the Window element in CustomerInformationEntry.xaml.
This is our view or visual representation finished with now, and all that remains is to instanciate a new CustomerInformationEntry from our other Window or UserControl, and to then display it. In this case I'm going to be putting a button onto the MainWindow.xaml, and providing it a click event which will create the instance of our new Window:
In MainWindow.xaml add <Button Name="BtnOpenCustomerInformationEntry" Content="Enter Customer Information" Click="OpenCustomerInformationEntry"/>. In my case I'll be adding the button inside my object, although you can put it wherever you like if you've already created your initial window.
In MainWindow.xaml.cs we'll add a new private method which will be used by the Click event of your new button. Adding the following code:
private void OpenCustomerInformationEntry(object sender, RoutedEventArgs e)
{
CustomerInformationEntry myWindow = new CustomerInformationEntry();
myWindow.Show();
}
That's it, you now have a button in your MainWindow.xaml which when clicked uses the OpenCustomerInformationEntry method defined in MainWindow.xaml.cs, which in turn makes an instance of your CustomerInformationEntry window and displays it.
If you would still rather stick with the Forms approach, you can do that by using WindowsFormsHost, usage of which is discussed here.
Best Regards,
JC

How to change view in WPF?

Have some free time and wanted to try making a game in WPF.
I was wondering, what is the best way of changing the view of a window?
I have made a "main menu" window, with three buttons.. New Game, Continue Game and Exit Game.
When pressing New Game I want the window to go to next "viewstate" for creation of player and such, dont want a new window to pop up. Whats the best way of implementing that.
It is appropriate to use DataTemplates if you want to dynamically switch Views depending on the ViewModel:
<Window>
<Window.Resources>
<DataTemplate DataType="{x:Type ViewModelA}">
<localControls:ViewAUserControl/>
</DataTemplate>
<DataTemplate DataType="{x:Type ViewModelB}">
<localControls:ViewBUserControl/>
</DataTemplate>
<Window.Resources>
<ContentPresenter Content="{Binding CurrentView}"/>
</Window>
If Window.DataContext is an instance of ViewModelA, then ViewA will be displayed and
Window.DataContext is an instance of ViewModelB, then ViewB will be displayed.
The best example I've ever seen and read it is made by Rachel Lim. See the example.
You could implement every gui you need as an UserControl and load the needed UserControl depending on your current step.

How do I use a button in Windows Phone 8 hub app

I am trying to change the context of a button inside a DataTemplate, but in my code-behind I can't acses it. What am I doing wrong?
Here is the XAML I am using:
<Grid>
<Hub>
<HubSection>
<DataTemplate>
<Grid>
<Button x:Name="THEbutten" Content="Button" HorizontalAlignment="Left" Margin="186,230,0,0" VerticalAlignment="Top"/>
</Grid>
</DataTemplate>
</HubSection>
</Hub>
</Grid>
Your Button is inside a DataTemplate, and therefore it is in a different context than the page and not accessible from it's codebehind.
Consider the following options:
Modify your Buttons Properties using Data Binding.
Create a UserControl for your HubSections Content.
Sadly, the Hub Control is fairly hard to understand and use for beginners, because of this DataTemplate.
Here are some tutorials:
Mikaelkoskinen - Getting started
DotNetCurry - The Windows 8.1 Hub Control
There are also several questions around here on that topic:
How to access controls within hubsections

WPF MVVM Why use ContentControl + DataTemplate Views rather than straight XAML Window Views?

Why This?
MainWindow.xaml:
<Window x:Class="MVVMProject.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid>
<ContentControl Content="{Binding}"/>
</Grid>
</Window>
Have your ExampleView.xaml set up as:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vms="clr-namespace:MVVMProject.ViewModels">
<DataTemplate DataType="{x:Type vms:ExampleVM}" >
<Grid>
<ActualContent/>
</Grid>
</DataTemplate>
</ResourceDictionary>
And create the window like this:
public partial class App : Application {
protected override void OnStartup(StartupEventArgs e) {
base.OnStartup(e);
MainWindow app = new MainWindow();
ExampleVM context = new ExampleVM();
app.DataContext = context;
app.Show();
}
}
When it can be done like this?
App.xaml: (Set startup window/View)
<Application x:Class="MVVMProject.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="ExampleView.xaml">
</Application>
ExampleView.xaml: (a Window not a ResourceDictionary)
<Window x:Class="MVVMProject.ExampleView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vms="clr-namespace:MVVMProject.ViewModels">
>
<Window.DataContext>
<vms:ExampleVM />
</Window.DataContext>
<Grid>
<ActualContent/>
</Grid>
</Window>
Essentially it's "View as DataTemplate" (VaD) vs. "View as Window" (VaW)
Here is my understanding of the comparison:
VaD: Lets you switch Views without closing the window. (This is not desirable for my project)
VaD: VM knows absolutely nothing about the View, whereas in VaW it (only) has to be able to instantiate it when opening another window
VaW: I can actually see my xaml rendered in the Designer (I can't
with VaD, at least in my current setup)
VaW: Works intuitively with
opening and closing windows; each window has (is) a corresponding View
(and ViewModel)
VaD: ViewModel can pass along initial window width, height, resizability etc. through properties (whereas in VaW they are directly set in the Window)
VaW: Can set FocusManager.FocusedElement (not sure how in VaD)
VaW: Less files, since my window types (e.g. Ribbon, Dialog) are incorporated into their Views
So what's going on here? Can't I just build my windows in XAML, access their data cleanly through properties of the VM, and be done with it? The code-behind is the same (virtually nil).
I'm struggling to understand why I should shuffle all the View stuff into a ResourceDictionary.
People use DataTemplates that way when they want to dynamically switch Views depending on the ViewModel:
<Window>
<Window.Resources>
<DataTemplate DataType="{x:Type local:VM1}">
<!-- View 1 Here -->
</DataTemplate>
<DataTemplate DataType="{x:Type local:VM2}">
<!-- View 2 here -->
</DataTemplate>
</Window.Resources>
<ContentPresenter Content="{Binding}"/>
</Window>
So,
if Window.DataContext is an instance of VM1, then View1 will be displayed,
and if
Window.DataContext is an instance of VM2, then View2 will be displayed.
Granted, it makes no sense at all if only 1 View is expected, and never changed.
Since in VaD the view models know nothing about the views, you can build a fully functioning application entirely made up of view models only and no views. This leads to the possibility of writing an application that can be driven entirely by code. This in turn leads to the possibility of performing integration testing without the GUI. Integration testing through the GUI is notoriously fragile - while testing through view models should be more robust.
From my personal experience:
Both work models are aviables, depending of what you want, and depending of the application requirements. The idea behind VaD is decopling the content, and the container. If you implement VaD you can use this template (by default) when ever you show any item of this type. You can use it in ItemsControls (lists, listviews, grids, etc) and in ContentControls only making bindings. Like you said, VaD works for switching the window's content with out closing and opening a new. Also you can define the view using UserControls, then you take control if focused elements, and also you can manage code behind. So, your data template may be like this:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vms="clr-namespace:MVVMProject.ViewModels">
<DataTemplate DataType="{x:Type vms:ExampleVM}" >
<CustomUserControl A="{Binding A}" B="{Binding B}" DataContext="{Binding}" .../>
</DataTemplate>
You also in an UserControl may set dependency properties, thats make easier the job, because allow bindings and decoupling the app.
But of course, if you app doesn't require dynamically content switching, it is fine to use VaW for the main window, or any other window. In fact, you can use both VaW and VaD. This last one can be used for inner items in the app, that doesn't require windows. You shoose what is better for you, depending of application requirements, and the time aviable for developing the app.
Hope this personal experience helps...

Categories