Moving MainWindow.xaml - c#

I've built a WPF app, which completely works now. However, to clean it up a bit I wish to move my MainWindow.xaml to the view folder I've created. After I've done this the application won't run and it gives me an "Unknown build error" which doesn't give any info on how to fix it...
What should I change in my MainWindow.xaml to let the app work properly again?
I've already changed
<Window x:Class="projectname.MainWindow">
to
<Window x:Class="projectname.view.MainWindow">
Should I change other stuff as well?

You don't need to update class name in xaml file unless you have changed the namespace of your class.
Most likely you haven't updated StartupUri for App.xaml. Change it to:
StartupUri="view/MainWindow.xaml"
from
StartupUri="MainWindow.xaml"

I just ran into this myself. Here's what I did:
Move your MainWindow.xaml to your new folder. In my case it was /Views.
I like to name all my classes with their namespaces reflecting their folder. So my MainWindow.xaml.cs namespace went from ProjectNamespace to ProjectNamespace.Views
In my MainWindow.xaml, I needed to change x:Class from ProjectName.MainWindow to ProjectName.Views.MainWindow.
In your App.xaml, change the StartupUri to reflect the folder. I went from StartupUri="MainWindow.xaml" to "StartupUri="Views/MainWindow.xaml"`
Doing this allowed me to compile and run my app.

The answer of #Rohit Vats is quite good!
However there's a good point to remember: you have to change all the absolute paths (in XAML) to your resources, prepending them by a / in order to indicate that these paths are relative to the root directory.
Example:
From <Image Source="Assets/Loading.gif">
To <Image Source="/Assets/Loading.gif"> and so on.

Related

How to handle resource loading in a control that is packed into a nuget?

I'm working on a generic 'window control' as I find I do a lot of the same things in the desktop apps I work on. I have a small project with a control, designed to go in a window in another project. This worked fine when in different projects (but the same solution), but now I have moved the window control to a new solution and packed it into a nuget, then referenced the nuget in my project with the window.
On initialising the window, it complains it can't find a resource that the control uses. For theming, when the user sets a theme (and on startup) an image which will best suit the brightness of the theme colour is picked and applied to a UI bound BitmapImage property. This is the resource that the usage of the control in my window in another project can't find, I get this error:
To me it seems the application I am using the control in is trying to find the pngs in its own resources, rather than that of the nuget. But I'm unsure on how to ensure the nuget functions only internally.
The two images to pick from are both set as 'Resource' and not to copy to output. I have also tried solutions where the images are simply copied to the output and read in via a relative path, however this doesn't seem to work:
On setting the theme, this code runs:
ThemeImage = isThemeDark
? new BitmapImage(new Uri(#"pack://application:,,,/Images/Pallete_Light.png", UriKind.Absolute))
: new BitmapImage(new Uri(#"pack://application:,,,/Images/Pallete_Dark.png", UriKind.Absolute));
This works fine on a test window in the same project as the control, the little colour pallete icon is the on being picked from:
My window is very simple, and is the same as the window from the project where it works.
<Window
x:Class="SomeApplicationName.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:SomeApplicationName" xmlns:win10themables="clr-namespace:Win10Themables;assembly=Win10Themables"
Title="SomeApplicationName"
Width="800"
Height="450"
AllowsTransparency="True"
Background="Transparent"
ResizeMode="NoResize"
WindowStyle="None"
WindowState="{Binding ElementName=WindowControl, Path=DataContext.WindowStateProperty, UpdateSourceTrigger=PropertyChanged}">
<win10themables:MainWindowControl x:Name="WindowControl" Title="SomeApplicationName" />
</Window>
In my App.xaml, I simply merge some resource dictionaries from the project the window control comes from so this project can use them:
<Application
x:Class="SomeApplicationName.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Win10Themables;component/ResourceDictionaries/Styles.xaml" />
<ResourceDictionary Source="/Win10Themables;component/ResourceDictionaries/Converters.xaml" />
<ResourceDictionary Source="/Win10Themables;component/ResourceDictionaries/Brushes.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
Sorry for the code dump. I'm at a bit of a loss on how to resolve this. I wanted to avoid repeatedly copying the base window project into each of my new projects, but at this point might be forced to do so anyway.
To anyone else who runs into this issue, I resolved this by keeping the images as resources, but then adding the images to a resource dictionary and merging that into the app.xaml of the project with the control, and referencing the image through Application.Current.Resource["ImageResourceName"] and casting to the type of my property (BitmapImage).
In my application where I consume this nuget (and add the control to the window), I also merge this resource dictionary into my app.xaml. This seems to resolve the issue, though I can't entirely understand the difference between referring it via the projects resources, and the resource dictionary, and why the latter resolves this. If anyone viewing this with this answer has any light to shed on this for mine and anyone elses benefit, please do!

How do I reconnect a XAML view file with it's code behind file?

I find very frequently that while I'm 'prototyping', and I change the base type of the code behind class, or something like that, that the two files become completely unaware of each other. Example:
XAML:
<UserControl x:Class="G4S.XTime.Modules.Employees.Details.Views.EmployeeGridView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
...
Code-behind:
namespace G4S.XTime.Modules.Employees.Details.Views
{
public sealed partial class EmployeeGridView: UserControl
{
public EmployeeGridView()
{
//InitializeComponent();
}
}
}
The call InitializeComponent produces a compile time error, saying it doesn't exist.
This disconnect phenomenon happens often enough to be costing me time, and I often just copy the code out of both files, delete the view, add a new view with the same name, paste the same code back, and everything works.
What am I missing that connects the two files? In the project file, I see the code-behind depends on the XAML, so I think if I comment out InitializeComponent, then compile with only the XAML, I will have the other part of my code-behind partial class. But this does not work. It doesn't seem to compile the XAML at all unless there is a code behind.
What can I do to reconnect these two files, in most cases?
Edit your project file and make sure you have something similar to this:
<Compile Include="EmployeeGridView.xaml.cs">
<DependentUpon>EmployeeGridView.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
For me the problem was caused by not having the correct way of including the files in the csproj file.
incorrect:
<CodeAnalysisDictionary Include="Windows\ConnectionSecuritySettings.xaml">
correct:
<Page Include="Windows\ConnectionSecuritySettings.xaml">
This happened when I moved the items to a new project
Make sure the declaration at the top of the xaml matches the code behind file with the full path including namespace.
eg. If namespace name is "MyControls" and Code behind Class is "MyNewControl" then
xaml declaration should be something like ..
<UserControl x:Class="MyControls.MyNewControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
Height="41" Width="77"
>
and code behind would be ..
namespace MyControls
{
/// <summary>
/// Interaction logic for MyNewControl.xaml
/// </summary>
public partial class MyNewControl: UserControl
{
#region Constructors
public MyNewControl()
{
InitializeComponent();
}
#endregion
}
}
I had the same problem (InitializeComponent could not be found) after a cut-paste of my XAML. The answer suggested here solved my problem. The suggestions is, in the Properties window of the XAML, change the Build Action to Page. Apparently the copy-paste can change the Build Action to Resource.
Hope this helps!
[Edit] I just wanted to add that this was also after updating the namespace for both the code-behind and in the xaml:
x:Class="NewNamespace.CodeBehindClass"

Customizing App.xaml.cs

I am trying to do some customization to App.xaml.cs to try to set some behaviors/events. Mostly researching, nothing special.
But whatever I do to the App.xaml.class there is no effect.
I even emptied the App.xaml.cs class (nothing in it) and the WPF program still compiles.
I cant even start learning until I solve this mystery.
There's no mystery. It's possible to completely empty App.xaml.cs, because it is a partial class. The App.xaml is perfectly capable of standing on its own.
To do customization, take a look at the Application class on MSDN, in particular the section under "Remarks", which has info about the application life cycle, and application-scope objects (window, resources).
If you want to do customization, you can implement a StartUp event, and do your customization there.
You define the event in App.xaml:
<Application x:Class="Test.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Startup="Application_Startup">
And if you remove the StartUpUri, you can also instantiate the main window for yourself.

BlankPage constructor cannot initialize components

I'm starting learning XAML and I add some code to my BlankPage application. And suddenly a constructor which is initializing a component:
public BlankPage()
{
this.InitializeComponent();
}
Stop working. I've got now that error:
'BlankApplication.BlankPage' does not contain a definition for 'InitializeComponent' and no extension method 'InitializeComponent' accepting a first argument of type 'BlankApplication.BlankPage' could be found (are you missing a using directive or an assembly reference?)
Honestly I didn't do anything, I didn't even look at this part of code and now it doesn't work.
Screenshot:
Just to give a bit more information on how to fix this (since this explanation is a bit on the vague side)..
This issue (for me) was caused because I changed the namespace in the code after I created the project. In order to fix this issue I had to make some changes in a couple of locations:
1: In App.xaml I had to change the following:
<Application
x:Class="New.Namespace.App"
2: In MainPage.xaml I had to change the following:
<Page
x:Class="New.Namespace.MainPage"
You will also want to make sure that you change the 'namespace' line in your App.xaml.cs as well as your MainPage.xaml.cs.
Finally, you will also want to make sure you update the Project Entrypoint in the Package.appxmanifest to point to "New.Namespace.App".
If your Main class's namespace is different than .xaml file's x:Class attribute, you will get this error. For instance;
Your MainPage.xaml.cs;
namespace UWPControls
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
}
}
}
Your MainPage.xaml;
<Page
x:Class="UWPControls_Different.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:UWPHelloWorld"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
</page>
You're going to see the error until changing x:class to the;
x:Class="UWPControls.MainPage"
This happens when you change a namespace for a class, you must do the same inside the XAML file.
There are two places inside the XAML file with the old namespace.
For me, the project was inside solution with other projects. When suggestions here did not work, a simple unloading and reloading the project from solution did the trick and fix all errors (with rebuilding of course).
My Solution: For my "SomePage : ContentPage", I changed the XAML properties:
Generator (Custom Tool): From MSBuild:Compile to MSBuild:UpdateDesignTimeXaml
BuildAction: From Page to Embedded resource
Using Visual Studio 2017 Enterprise 15.3.4
Problem solved.
Cause: I forgot to also change custom application name in xaml code.
Solution: I have changed application name in XAML, now it works well.

Window implemented in subfolder not avaiable for StartUri

A novice question about WPF.
I'm just at the beginning of a draft project.
I have define a really simple window testWindow1.xaml, located in the solution subfolder Tests.
In App.xaml I cannot do:
StartupUri="testWindow1.xaml"
(unless I move the testWindow1.xaml back to the root of the project)
I have also tried defining my namespace into the App.xaml tag, but without success, this wont work either.
<Application x:Class="MyProject.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:myprojectNS="clr-namespace:MyProject"
StartupUri="myprojectNS.tests.testWindow1.xaml">
At run time, the exception message complains about not finding the ressource *testWindow1.xaml
Try this -
<Application x:Class="MyProject.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:myprojectNS="clr-namespace:MyProject"
StartupUri="tests\testWindow1.xaml">
You just need to specify the hierarchy.

Categories

Resources