Weird case-insensitive behaviour in WPF - can you please explain - wpf

Can someone please explain this to me:
I have removed the startupUri in my application and moved it to the app class.
<Application x:Class="My.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
><!-- StartupUri="/Forms/MainWindow.xaml"-->
<Application.Resources>
</Application.Resources>
</Application>
I accidently typed "mainWindow" with a lower case in "var mainWindow" but I reference it with an upper case in "MainWindow.Show();".
public partial class App : Application
{
public App()
{
var mainWindow = new MainWindow();
MainWindow.Show();
}
}
Please note that MainWindow doesn't refer to the class here, but in fact to the lowercase mainWindow object.
Why is this then working fine? I thought it should throw an compiler error?
How can mainWindow and MainWindow refer to the same object?

The application has a main window of type MainWindow which initially is "MainWindow" generated in your project. If you use a instance, or this property the result should be the same.
Here you have a picture with the application content and the MainWindow property:

The MainWindow object you're accessing with MainWindow.Show() is actually a property of the Application class. It's just a coincidence that your main window is also called 'MainWindow'.
According to MSDN, the Application.MainWindow property "is automatically set with a reference to the first Window object to be instantiated in the AppDomain."
Your code var mainWindow = new MainWindow(); is effectively doing that: instantiating the first instance of a Window object in your AppDomain. So the subsequent attempt to access Application.MainWindow will return your newly created Window object.
The behaviour is correct, but it is a little confusing.
MSDN: https://msdn.microsoft.com/en-us/library/system.windows.application.mainwindow(v=vs.110).aspx

Related

Generic ReactiveUserControl "cannot be edited in Design view"

I changed my UserControl to be a ReactiveUserControl and now I can't view the Design View. Is there anything I can do to get the designer to work with ReactiveUserControl?
The Visual Studio designer has issues when your control or window directly inherits from a generic class. This was a pretty common issue with WinForms as well. You can work around this issue by defining another non-generic class that sits between the generic ReactiveUserControl and your control:
public partial class MyUserControl : MyUserControlBase
{
public MyUserControl()
{
InitializeComponent();
}
}
public abstract class MyUserControlBase: ReactiveUserControl<MyUserControlViewModel>
{
}
In the XAML, our root object element is defined as the base element (MyUserControlBase) and its class declaration is connected to the partial class defined above (MyUserControl):
<myNameSpace:MyUserControlBase
x:Class="MyNameSpace.MyUserControl"
xmlns:myNameSpace="clr-namespace:MyNameSpace"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

Calling a custom dependency property defined in code-behind from XAML

Is it possible to call a custom dependency property in the XAML of the element in which it is defined?
I mean, i have the following simple code for my mainWindow:
Code
public partial class MainWindow : Window
{
public static readonly DependencyProperty SpecialToProperty = DependencyProperty.Register("SpecialTo", typeof(double), typeof(MainWindow));
public MainWindow()
{
InitializeComponent();
}
public double SpecialTo
{
get
{
return (double)GetValue(SpecialToProperty);
}
set
{
SetValue(DoubleAnimation.ToProperty, value);
}
}
}
How can i use that dependency property from the XAML partial code of the MainWindow class?
I mean something like:
<Window x:Class="WpfAnimationTEst.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525"
SpecialTo=200>
I know it can be done using attached dependency properties, but is it the only way? Is it not possible to call a dependency property defined in the code-behind?
Thank you and sorry if the question is some kind of stupid, i'm just learning and trying to understand WPF.
I found the answer after I initially posted a wrong answer:
The problem really lies in circular dependencies if you use andreask's answer. I had to create a BaseClass for all windows:
1) Create a new Window Base Class:
public class BaseWindow : Window {
public BaseWindow() { }
public static readonly DependencyProperty SpecialToProperty = DependencyProperty.Register("SpecialTo", typeof(double), typeof(BaseWindow));
public double SpecialTo {
get {
return (double)GetValue(SpecialToProperty);
}
set {
SetValue(SpecialToProperty, value);
}
}
}
This will be the new baseclass for all your windows.
2) Modify your MainWindow xaml: (Change YOURNAMESPACE (2x) to your namespace name)
<local:BaseWindow x:Class="YOURNAMESPACE.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:YOURNAMESPACE"
Title="MainWindow" Height="350" Width="525" SpecialTo="100">
<Grid>
</Grid>
</local:BaseWindow>
3) And you also need to modify your partial MainWindow.cs:
public partial class MainWindow : BaseWindow {
public MainWindow() {
InitializeComponent();
}
}
That worked for me, however, you will always need to use the extra xaml markup in your window declaration.
I'm answering my own question because there seems to be many ways to solve it correctly. I've upvoted the answers that best helped me, but i can't set any as the correct answer since all are correct.
So i'll just post a conclusion. If you think that i'm mistaken, please post a comment and i will correct my mind.
The main answer to my question is no, it is not possible to directly call a custom dependency property defined at code-behind from its "linked" XAML file. It is mandatory to instantiate the control in which the property is defined to call it.
To me, the best workarrounds to use a custom dependency property in XAML, defined in the code-behind are the posted by #Clemens and #Noel Widmer. This and this
You can use custom dependency properties in XAML, but only if you instantiate the control in XAML. For example, take a customized TextBox element:
public class MyTextBox : TextBox
{
public static readonly DependencyProperty SpecialToProperty = DependencyProperty.Register("SpecialTo", typeof(double), typeof(MyTextBox));
public double SpecialTo
{
get
{
return (double)GetValue(SpecialToProperty);
}
set
{
SetValue(DoubleAnimation.ToProperty, value);
}
}
}
You can of course create an instance of MyTextBox in XAML and assign the SpecialTo property there:
<custom:MyTextBox SpecialTo="1.0" />
In your case, however, you're not instantiating the custom class MainWindow, but you create a new instance of class Window, and the Window class isn't aware of the custom dependency property (the SpecialTo property is not even available in Window, since you declared it within the MainWindow class).
For the dependency property to be recognized, you'd need to instantiate MainWindow directly:
<custom:MainWindow
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525"
SpecialTo=200>
However, this means you need to omit the x:class directive that used to combine XAML and codebehind of your window (otherwise you'd run into circular dependencies), and I'm not sure if this correctly initalizes your window...
Yes, it is possible. Dependency properties are used to bind within XAML. If you want to bind to property defined in the code behind window you need to reference this window as XAML element, i.e. add tag for your main window x:Name="mainWindow", and next in the binding expression refer it as ElementName=mainWindow

How to access controls from MainWindow?

I have a text box in the MainWindow. I was wondering how I can access it from another window. I tried declaring an instance of the MainWindow but it doesn't work. Say I want to set the text in the MainWindow to something, in SecondWindow. How can I do that? Thanks!
Expose a public function on MainWindow that will allow you to set some property on it. Then when creating the new window pass an instance of MainWindow to its constructor. Now from within this new window call the public function you have exposed.

XamlParseException thrown calling XamlReader.Load

I'm playing around with .net 4's System.Windows.Markup.XamlReader - just as an education exercise - and I keep bumping into the same problem: Loading xaml with XamlReader.Load throws a XamlParseException if the root object defines an x:Class, but successfully parses and loads the node if not.
Here's the code I'm trying:
using System.Windows;
using System.Xaml;
using XamlReader = System.Windows.Markup.XamlReader;
namespace WpfApplication2
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
// Load up UserControl1.xaml from the solution
var reader = new XamlXmlReader(#"../../UserControl1.xaml", XamlReader.GetWpfSchemaContext());
var userControl = XamlReader.Load(reader) as UserControl1;
// Do something with userControl...
}
}
}
I've tried XamlReader.Parse directly from a string holding the xaml with the same result: only works if no x:Class declaration is defined.
Removing the x:Class declaration doesn't seem like a good option, because then I lose the code-behind, specifically the call to InitalizeComponent()
The exception detail:
'Specified class name 'WpfApplication2.UserControl1' doesn't match actual root instance type 'System.Windows.Controls.UserControl'. Remove the Class directive or provide an instance via XamlObjectWriterSettings.RootObjectInstance.'
...but I don't know how (where) to set XamlObjectWriterSettings.RootObjectInstance (or indeed, if that's required?)
Any clues?
XamlReader is a parser, not a compiler, so doesn't support code-behind. If you need to associate code with your dynamically loaded XAML you can do something like wrapping it up into a control defined elsewhere that you can use an instance of in the XAML or, after reading in the XAML, connect up the code (i.e. event handlers) to elements in the resulting object.
You can't use x:Class in dynamic XAML. Instead what you can do is you can hook events after the loading XAML. please have a look at this link
Loading XAML XML through runtime?

WPF - UserControl inheritance

I have problem with control inheritance in WPF. I created a UserControl named BaseUserControl. I want for this control to be a base control for other WPF userControls. So I wrote another UserControl called FirstComponent. In next step I changed this code
FirstComponent : UserControl
to this
FirstComponent : BaseControl
However during compilation I get this error
Partial declarations of 'controlinheritance.componenets.FirstComponent' must not specify different base classes
What should I do to enable FirstComponent to derive from BaseControl?
EDIT
Thanks to abhishek answer I managed to inherit controls . Howerver I have another question. In base class I specified a property public Grid _MainGrid { get; set; }. Now I want in my derived class create an instance of this grid. So I used this code
Howerver I get an error Property '_MainGrid' does not have a value. Line 8 Position 36.
Did you see my complete article on it?
http://www.dotnetfunda.com/articles/article832-define-base-class-for-window--usercontrol-.aspx
I hope that would help you in this.
If you try to execute the project, it would definitely throw error to
you. This is because, every WPF window is created from the baseWindow
layout rather than the current Window layout. In other words, if you
see the XAML, you will see the root tag is Window, which is a class
just parent of the current window.
Thus to ensure everything works perfectly, we need to change the Root
Element.
So it would look like :
<local:BaseWindow Class="BaseWindowSample.Window1"
Name="winImp"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:BaseWindowSample"
Title="Window1">
...
</local:BaseWindow>
If you see this minutely, you can see I have added one namespace to my
project and named it as local. So BaseWindow should come from
BaseWindow and thus it goes like local:BaseWindow
Well the reason for the initial error was because the class was actually a partial class that was listing a particular base inheritance somewhere else in addition to the location where you changed your base class.
As for your property 'inheritance', I suggest trying
public Grid MainGrid
{
get
{
return base.MainGrid;
}
set
{
base.MainGrid = value;
}
}
However I should note that this will not give you a link to any existing instance(s) of your base class. If you want there to be a guaranteed link in your derived class to the lone instance of that Grid, then you will have to make the base class property a static.
In which case, your code will look like this...
public Grid MainGrid
{
get
{
return BaseControl.MainGrid;
}
set
{
BaseControl.MainGrid = value;
}
}
When you specify a Different base class for a Usercontrol in the XAML.cs file
FirstComponent : BaseControl
You should also change this in the XAML
<Base:BaseControl x:Class="FirstComponent"
xmlns:Base="clr-namespace:MyApplication.Base"
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"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
</Grid>
</Base:BaseControl>

Resources