WPF: What is App.xaml's Purpose? - wpf

I've done .Net development for awhile but I'm new to the WPF technology. What is the supposed purpose of App.xaml? Also, what type of xaml code do you usually put in it? It seems like for simple applications it could be ignored and left untouched. Is this true?

App.xaml is the declarative portion of your code (usually generated by Visual Studio) extending System.Windows.Application. For example, Expression Blend can use App.xaml to share a Resource Dictionary or a design-time data set with your entire application. And, because we are using Microsoft products, whatever Expression Blend can do auto-magically, we can do by hand in Visual Studio.
Now the tangent: To me, to ask about the purpose of App.xaml is to ask about the purpose for System.Windows.Application. Feel free to accuse me of changing the original question (let the digital brutality ensue).
You can’t just open a System.Windows.Controls.Window in any Assembly you like… Chris Sells is likely telling me this in his book. I began to understand the purpose of System.Windows.Application while using MEF and MVVM Light to display WPF windows in DLLs (not EXEs). I got errors like this:
The type 'System.Windows.Markup.IComponentConnector' is defined in an assembly that is not referenced.
or
The type 'System.Windows.Markup.IQueryAmbient' is defined in an assembly that is not referenced.
The above error is simply saying that I’m trying to open a WPF Window inside of a DLL and not an EXE. Then, there’s this error:
The component 'Songhay.Wpf.WordWalkingStick.Views.ClientView' does not have a resource identified by the URI '/Songhay.Wpf.WordWalkingStick;component/views/clientview.xaml'.
This boils down to the absence of a facility that associates WPF Window XAML with the WPF “code” (an instance). This facility is associated with WPF EXEs and not WPF DLLs. Visual Studio auto-generates a WPF EXE class called App.g.cs (in your \obj\Debug folder) with this call in it: System.Windows.Application.LoadComponent(this, resourceLocater) where resourceLocater is a badly named variable containing a System.Uri pointing to the XAML like ClientView.xaml mentioned above.
I’m sure Chris Sells has a whole chapter written on how WPF depends on System.Windows.Application for its very life. It is my loss (quite literally of time) for not having read about it.
I have shown myself a little something with this unit test:
[STAThread]
[TestMethod]
public void ShouldOpenWindow()
{
Application app = new Application();
app.Run(new Window());
}
Failing to wrap a new Window in the System.Windows.Application.Run() method will throw an error from the land of COM talking about, “Why did you pull the rug from underneath me?”

For simple applications, it is true, it can be ignored. The major purpose for App.xaml is for holding resources (style, pens, brushes, etc.) that would would like to be available through out all of the windows in your application.

It is true. App.Xaml is some sort of central starting point. You CAN use it, or you CAN start your first window (it is defined in the app.xaml) manually. There are some lifetime events there centralls (like application start).

Storing resources that are used across the whole application.
Application is the root of the logical tree.

It is like Global.asax if you are coming from an ASP.NET background. You can also use it to share resources throughout your application. Comes in pretty handy for resource sharing.

App.xaml is a major part of wpf application.
It contains major four attributes
1.X:Class->used to connect you xaml and code-behind file(xaml.cs).
2.xmlns->To resolve wpf elements like canvas,stack panel(default one).
3.xmlns:x->To resolve XAML language definition.
4. StartupUri->To give start window when application is launching.

++++++++
App.xaml is the declarative starting point of your application. Visual
Studio will automatically create it for you when you start a new WPF
application, including a Code-behind file called App.xaml.cs. They
work much like for a Window, where the two files are partial classes,
working together to allow you to work in both markup (XAML) and
Code-behind.
App.xaml.cs extends the Application class, which is a central class in
a WPF Windows application. .NET will go to this class for starting
instructions and then start the desired Window or Page from there.
This is also the place to subscribe to important application events,
like application start, unhandled exceptions and so on.
One of the most commonly used features of the App.xaml file is to
define global resources that may be used and accessed from all over an
application, for instance global styles.
+++++++++
Source : http://www.wpf-tutorial.com/wpf-application/working-with-app-xaml/

Here is an updated answer in case people are still looking.
There is this excellent article on WPF, and the link specifically puts you at the App.Xaml point to begin teaching you the things you can do with it.
WPF is easy for the first very simple app or two. However, due to the increased flexibility of the framework, you need these types of tutorials to help you understand what can be done from where (in the various application files).
https://www.wpf-tutorial.com/wpf-application/working-with-app-xaml/
Good luck.

Related

Best Starting Point for WPF Revit Add in

I am wanting to rewrite one of my Revit Add ins so that it utilizes WPF with MVVM because I like the look and functionality of WPF better than Windows Forms.
I have used the Revit Template Wizzard from Jeremy Tammik for the Form based add in, but adding a WPF user control seems not to work (a run time error that the xaml resource cannot be found).
I found a WPF MVVM revit add in example (AddMaterials, here is the github link, which will add materials from an Excel spreadsheet) but it does not follow what I am expecting to see at the top level.
Revit Add ins have an app.cs file which tells Revit how to register and access the DLL (ribbon panel buttons etc).
A windows WPF app will have app.xaml as the top level entry point.
The Add Materials project has neither which tells me that it must be
a class library, however the views are not using UserControls
rather they are Windows which I prefer. However Visual Studio does not
let you add a Window for a Class Library type project.
The third issue is easily solved by simply copying windows from a WPF application project into a class library project. But I don't really understand how the class library will instantiate in Revit without following the app.cs code from the template. Is anyone else creating add-ins this way, and if so can you let me in on any tricks or discussions that will help? Has anyone created a WPF Revit addin template for Visual Studio?
When I add a WPF window and try to instantiate it I get an error that it cannot find the xaml resource (System.IO.IOException: Cannot locate resource 'xxxx.xaml'). I have tried to fix this according to advice found when googling for this error, but to no avail. I am thinking it comes from being in a form based project, and that I may have to just start with a new project without the form stuff.
I have now verified that indeed you can start with the Revit AddIn Wizzard and use WPF . . . I started from scratch and copied in a window created in another project and got it to run (after adding the various references, namespaces, etc). So my problem seems to just be with the original project which already had a bunch of form stuff added.
Yes, I'm using WPF to create Revit Addins. It works well. You can easily create your own WPF template from the SDK samples:
Start with one of the Autodesk-provided SDK samples. I used the "DockableDialogs" sample. I know this one works, your mileage may vary with the others. If you're looking for windows rather than docked panes in the UI, another sample (perhaps the AddMaterials sample) is probably simpler.
I used Visual Studio to turn the sample into a template. File - Export Template -> select "DockableDialogs" or other WPF sample project.
Create a new project based on the template you just created. This was the easiest method I could find to get the WPF internal bits wired up correctly.
I'm not specifically familiar with the AddMaterials project, but to clarify your bullet points.
Revit Addins - It's not the file name (app.cs) but rather they must extend IExternalApplication or IExternalCommand. If you are creating a xaml interface (rather than just running a command from a ribbon button) you'll use 'IExternalApplication' as your entry point. Look for something like this in the sample:
public class ThisApplication : IExternalApplication ...
I don't used a top level app.xaml, but instead have page.xaml pages which are called by the Revit app. In my case these are Pages rather than Windows, which extend the IDockablePaneProvider class. These must be registered with the application which can then can be show, hide, etc your Panes. I imagine this is simpler with Windows, but haven't done it myself. For the dockable panes, your xaml.cs should start out something like:
public partial class MainPage : Page, Autodesk.Revit.UI.IDockablePaneProvider ...
Yes, the project is a class library in the sense that it is a collection of classes, at least one of which extends IExternalApplication or IExternalCommand. Remember that you're not creating a standalone application, but adding functionality to an existing Windows application (Revit). Revit will instantiate the ThisApplication class and then call its .OnStartup() method when the Revit application starts. This shouldn't stop you from adding .xaml or .cs files to the project, though. I can do it using VS Community 2015 using Ctrl-Shift-A.
Hopefully this gets you started - I've been able to implement a WPF UI in Revit without any prior WPF experience, and I'm not even a real programmer, so it's definitely possible. Good Luck!
addendum
If you want to add WPF elements to an existing revit addin, you can follow the instructions here: How can I connect xaml and xaml.cs files
Ultimately I found it easier to migrate my addin code into a template made from a working sample, you may want to try this approach as well.

How should I relate WPF MainWindow "mainloop" with application logic's "mainloop"

When we create a WPF project in Visual Studio (2010), it automatically creates a MainWindow.xaml, whose code-behind contains a MainWindow class with an InitializeComponent() in it. I know superficially that, somewhere in the project files, there is an actual main() function equivalent for the presentation, so that when the application GUI is loaded the GUI events are handled "downwards" the application layers - as soon as they exist.
I plan to develop something in the lines of Model-View-Presenter application, and I am already mocking very rudimentar domain-logic and application façade.
My doubt is: when I have my domain logic, how should I connect the Presenter with the Application Façade, or more pragmatically, WHERE and how (in the project files) I should start to "flesh out" the application from a blank WPF Application created in Visual Studio. I have made something like Add Existing Project, but than staled.
(EDIT: From a design patterns book: "An application facade is opened with a particular object in the domain model as the subject. This subject acts as the starting point for all the manipulations that are done by the facade." That seems a good start for the initiated...)
Is there any common, obvious or best-practice way of doing it?
(also, if someone could suggest / edit a better title for this question, I'd appreciate that)
Thanks for any help!
This guide from Microsoft (though a bit old) explains the layers and parts of a Rich Gui application rather well: http://msdn.microsoft.com/en-us/library/ee658087.aspx
How you're actually structuring your projects and files is really up to you. You can build a stand-alone application in one project. You won't be able to re-use that code very easily, but your WPF application won't notice.
You can group your classes in multiple ways. By Namespace, by assembly (project), nested class etc... When to use which is usually up to re-use or distribution over different machines.
When you build a UI part and a webservice part, you'll probably stick each in a different project.
When you want to re-use your business classes in a website and a windows app and a phone app, you'll probably want to stick them each in a different project.
Separating into projects prevents you from creating circular dependencies between classes.
Usually you'll get a chain of projects from the UI referencing the Business Layer referencing the Data layer etc. And you'll often see a couple of cross cutting concerns (logging and security for example) that are references from each of these 'layers'.
In the end, a layer can map to a Project (assembly) or a Namespace (within a project). Which one you choose is up to you.
In a WPF project the application entry point is specified by the App.Xaml. You'll find a reference to the main Form to load in there.
<Application x:Class="WpfApplication1.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml"> <-- Start up here -->
<Application.Resources>
</Application.Resources>
</Application>
The actual entry point is defined in your project settings:
You can start any initialization code in the App.xaml.cs. The simplest way is by subscribing to the OnStart event or the OnLoadCompleted event. You can also start your logic in the MainWindow.xaml.cs code. Place the actual logic in a separate class and reference that from your OnStart or OnLoadCompleted events.
And add your own code there
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
private void Application_Startup(object sender, StartupEventArgs e)
{
}
}
A better, more object oriented and unit testable way is to use Prism or MVVM Light. The scope of these frameworks is so large that they warrant their own topic.
I'm not sure why you would want a mainloop. Unless you plan to do some kind of game or 3d rendering. In the other cases you can suffice by adding commands to the visible objects and let Windows handle the primary input registration and dispatching of events. For long-running tasks you can use threading to have that done in the background (different topic again).

Why does the Application class (App) have both xaml and code behind files?

In WPF applications all the views are inherited from System.Windows.Window and have an associated xaml and codebehind file. That seems logical.
However I'm confused that why does the App file, inherited from System.Windows.Application, have a xaml file? Although it is an application and not a view (It is not visible)? I know that this file is usually used to define application resources, etc, and xaml provides an efficient way of defining them. But that can also be done programatically. Then what benefit did the designers of wpf achieve by having both the xaml and code behind files for "App"? Wouldn't one of them have been enough?
However I'm confused that why does the App file, inherited from System.Windows.Application, have a xaml file? Although it is an application and not a view (It is not visible)?
Remember that XAML is not a UI language, but a general declarative language. While it's true that it's mostly used to represent UI for WPF or SilverLigth, it's also used to declare graph of objects in other non-UI technology.
The first example that comes into my mind is the Workflow (the XOML is a derivate of the XAML), SharePoint also use XAML in some hidden parts, and I've seen in a customer project with use XAML as a meta-language for generating web-apps (and yes, it actually outputs HTML).
Then, to answer to your question, the application have both files (and it is not actually a requirement) because you can :
declare some objects (in the xaml)
override the behavior of the application (by overriding appropriate methods)
Designers can specify resources for entire application without entering any code and use it in any Window. Its something like a root for all windows. For example, if you use one style for every TextBox (or any other control) in every window, you can specify it in App.xaml and bind anywhere without duplicating.

Final steps in using MVVM to decouple GUI from business logic?

Just recently, I learned about using MVVM to decouple GUIs from the underlying model. I ended up learning as much as I could to convert my current application over to MVVM, and was largely successful. Now I need to figure out how to actually take a GUI generated in Blend and use it in place of my current GUI, which was designed in Visual Studio. I can't find any resources on the web for making this as seamless as possible. I'd like to know what you all have done and have had work for you.
My ultimate solution would be something that would allow me to, at runtime, select a skin from a menu and immediately have the GUI change from the current one to another that the user selects. Can anyone point me to posts that explain how to do this?
My current goal is less ambitious -- I'd like to be able to add my new Blend GUI into my Visual Studio project and when I compile, have the new Blend GUI appear. If I want to go back to the old GUI, I would have to recompile. For now, that is okay.
I've got my Blend project added to my VS2008 solution, and have set it to be the startup application. That works fine -- if I run the app, my new GUI appears instead of the old one. The problem now is that it needs DLLs that are actually in a different folder -- the bin\Debug folder of the original startup application. Am I supposed to leave my original GUI as the startup application, and then have its App codebehind load the other GUI?
Also, each of the respective GUIs needs a reference to the ViewModel. In my case, I was just instantiating it in my current GUI class. For the Blend GUI, I instantiated one there as well, since only one of the GUIs will be active. Is this where something like the Unity framework should be used?
Sorry about all of the possibly-incoherent questions, but I'm not quite sure how I should proceed from here. I feel like I'm so close to proving to myself that MVVM is the way to go from a GUI standpoint (I'm already sold on the testability bit).
All the examples I've seen dynamically switch GUI appearance by using some form of ResourceDictionary swapping. A few links:
Load XAML Resource Dictionaries at Runtime
WPF change theme/style at runtime
Hope that helps.
I found a mistake, where in one part of my code I was using the wrong property to get at the currently-running assembly's path. I am now using
System.Reflection.Assembly.GetExecutingAssembly().Location
Although this does work, it only works if I copy the exe from the Blend project's bin\Debug folder into my main application's bin\Debug folder. I will have to live with this by using a post-build event, I guess. I was so spoiled for the past several months working with .NET, where I didn't have to do this (like before in C++) because all of the referenced assemblies get automatically copied over. If I want to debug any code-behind, I also have to set the starting executable in the Blend project's settings, which is inconvenient as well, especially when working on different computers where the paths aren't set up the same. Any suggestions here would also be appreciated!

What approaches are available to dummy design-time data in WPF?

I am working without expression blend and just using the XAML editor in vs2010. The wisdom of this aside, I am increasingly seeing a need for design-time data binding. For simple cases, the FallbackValue property works very nicely (Textboxes and TextBlocks, etc). But especially when dealing with ItemsControl and the like, one really needs sample data to be visible in the designer so that you can adjust and tweak controls and data templates without having to run the executable.
I know that ObjectDataProvider allows for binding to a type, and thus can provide design-time data for visualizing, but then there is some juggling to allow for the real, run-time data to bind without wasting resources by loading loading both the design time, dummied data and the runtime bindings.
Really what I am wanting is the ability to have, say, "John", "Paul", "George", and "Ringo" show up in the XAML designer as stylable items in my ItemsControl, but have real data show up when the application runs.
I also know that Blend allows for some fancy attributes that define design time binding data that are effectively ignored by WPF in run-time conditions.
So my questions are:
1. How might I leverage design-time bindings of collections and non-trivial data in the visual studio XAML designer and then swap to runtime bindings smoothly?
2. How have others solved this design-time vs. runtime data problem? In my case, i cannot very easily use the same data for both (as one would be able to with, say, a database query).
3. Are their alternatives to expression blend that i could use for data-integrated XAML design? (I know there are some alternatives, but I specifically want something I can use and see bound sample data, etc?)
Using VS2010 you can use Design-Time attributes (works for both SL and WPF). I usually have a mock data-source anyway so it's just a matter of:
Adding the namespace declaration
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
Adding the mock data context to window/control resources
<UserControl.Resources>
<ViewModels:MockXViewModel x:Key="DesignViewModel"/>
</UserControl.Resources>
Setting design-time data context
<Grid d:DataContext="{Binding Source={StaticResource DesignViewModel}}" ...
Works well enough.
As an amalgam of Goran's accepted answer and Rene's excellent comment.
Add the namespace declaration.
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
Reference your design time data context from code.
<Grid d:DataContext="{d:DesignInstance Type=ViewModels:MockXViewModel, IsDesignTimeCreatable=True}" ...
I use this approach for generating design time data with .NET 4.5 and Visual Studio 2013.
I have just one ViewModel.
The view model has a property IsInDesignMode which tells whether design mode is active or not (see class ViewModelBase).
Then you can set up your design time data (like filling an items control) in the view models constructor.
Besides, I would not load real data in the view models constructor, this may lead to issues at runtime, but setting up data for design time should not be a problem.
public abstract class ViewModelBase
{
public bool IsInDesignMode
{
get
{
return DesignerProperties.GetIsInDesignMode(new DependencyObject());
}
}
}
public class ExampleViewModel : ViewModelBase
{
public ExampleViewModel()
{
if (IsInDesignMode == true)
{
LoadDesignTimeData();
}
}
private void LoadDesignTimeData()
{
// Load design time data here
}
}
Karl Shifflett describes an approach that ought to work equally well for VS2008 and VS2010:
Viewing Design Time Data in Visual Studio 2008 Cider Designer in WPF and Silverlight Projects
Laurent Bugnion has a similar approach that focuses on Expression Blend. It might work for VS2010, but I haven't confirmed this yet.
Simulating data in design mode in Microsoft Expression Blend
Maybe the new design-time features of Visual Studio 2010 and Expression Blend 4 are an option for you.
How it works is shown in the BookLibrary sample application of the WPF Application Framework (WAF). Please download the .NET4 version.
Similar to the top rated answer, but better in my opinion: You can create a static property to return an instance of design data and reference it directly from XAML like so:
<d:UserControl.DataContext>
<Binding Source="{x:Static designTimeNamespace:DesignTimeViewModels.MyViewModel}" />
</d:UserControl.DataContext>
This avoids the need to use UserControl.Resources. Your static property can function as a factory allowing you to construct non-trivial data types - for example if you do not have a default ctor, you can call a factory or container here to inject in appropriate dependencies.
Using Visual Studio 2017 I have been trying to follow all of the guides and questions such as this and I was still facing a <ItemsControl> which simply did not execute the code I had inside the constructor of a DesignFooViewModel which inherits from FooViewModel. I confirmed the "did not execute" part following this "handy" MSDN guide (spoiler: MessageBox debugging). While this is not directly related to the original question, I hope it will save others a lot of time.
Turns out I was doing nothing wrong. The issue was that my application needs to be built for x64. As the Visual Studio is still in 2018 a 32-bit process and apparently cannot spin a 64-bit host process for the designer part it cannot use my x64 classes. The really bad thing is that there are no errors to be found in any log I could think of.
So if you stumble upon this question because you are seeing bogus data in with your design time view model (for example: <TextBlock Text="{Binding Name}"/> shows up Name no matter you set the property to) the cause is likely to be your x64 build. If you are unable to change your build configuration to anycpu or x86 because of dependencies, consider creating a new project which is fully anycpu and does not have the dependencies (or any dependencies). So you end up splitting most or all but the initialization parts of the code away from your "WPF App" project into a "C# class library" project.
For the codebase I am working on I think this will force healthy separation of concerns at the cost of some code duplication which is probably net positive thing.
I liked jbe's suggestion, specifically to look at how they do it in the WAF framework sample apps - they use separate mock/sample view models in a DesignData folder and then have a line like this in the XAML:
mc:Ignorable="d"
d:DataContext="{d:DesignInstance dd:MockHomeViewModel, IsDesignTimeCreatable=True}"
(where dd points to the .DesignData namespace where MockHomeViewModel lives)
It's nice and simple (which I like!) and you can inherit from the real VMs and just provide dummy data. It keeps things separate as you don't need to pollute your real VMs with any design time only code. I appreciate things might look quite different for a large project utilising IOCs etc but for small projects it works well.
But as joonas pointed out, it seems not to work with x64 builds in VS2017 and this still seems to be the case with VS2019 (I'm using V2019 16.6 Community edition). It's not fiddly to get working to start off with but can cause some head scratching when after making a change (or as is usually the case, several changes!) it suddenly stops working.
For anybody trying it, I would recommend creating a new simple WPF project (say one view, one view model, one mock vm) and play around with it; get it working and then break it. I found sometimes, no amount of solution cleans and rebuilds would fix it, the only thing that worked was closing VS down and restarting, and suddenly my design time data came back!

Resources