WPF - UserControl inheritance - wpf

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>

Related

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

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

How to show ContentControl in designer when using Calibrun.Micro viewModel-first approach?

I'm using Caliburn.Micro (CM) in a WPF application with ViewModel-first approach. I'm composing the main view with a command bar and an active item. Main viewModel sets the property for the command bar viewModel, and navigates to active item correctly.
Everything looks fine at runtime, the issue is only related to design-time: the main view shows empty in designer and I cannot find how to set it correctly. I managed to having this working in other scenarios, e.g. when setting the datacontext at design time for a whole Window or UserControl, i.e. when that's the root UI element in XAML. But now I'm not able to to this for child ContentPresenter UI elements within a Window.
This is an excerpt of the main view I'm composing:
<Window x:Class="...MainView" ...>
<DockPanel ...>
<!-- this one binds to a property of type CommandBarViewModel -->
<ContentControl x:Name="CommandBar" ... />
<ContentControl x:Name="ActiveItem" ... />
</DockPanel>
</Window>
I've checked a number of related reads, but none of them seems to fit/solve my issue. This question is basically the same as mine, but has no answers. That has a reference to this other question which it seems to me is going for a View-first approach, judging by the cal:View.Model bindings.
I tried adding a design-time context like the following (fake namespace not shown for brevity):
<ContentControl x:Name="CommandBar" ...
d:DataContext="{d:DesignInstance Type=fake:DesignTimeCommandBarViewModel, IsDesignTimeCreatable=True}"
cal:Bind.AtDesignTime="True"/>
but then I incur in one of two cases:
if DesignTimeCommandBarViewModel inherits from the actual CommandBarViewModel, then I incur in somewhat the usual problem of design-time Vs dependency injection: the default constructor passes null for all injected dependencies, and base constructor or something else gives problem. I mean, it seems it would take some effort to find a workaround for this, and just for design-time support
if DesignTimeCommandBarViewModel does not inherit from the actual viewModel, then it seems that (correctly) the CommandBarView is not instantiated, as now there's no relationship anymore between the viewModel and that view.
Have you got any idea about this? Maybe this should be solved with a design-time version of the hosting MainViewModel?
Other references I checked: this answer, from Rob Eisenberg himself, this CM thread, this other SO
Edit
Following my last (auto-)hint, I'm trying also creating and instantiating a DesignTimeMainViewModel, not inheriting from MainViewModel, which exposes the same properties and sets a DesignTimeCommandBarViewModel in its default constructor. In this case, in place of the command bar the designer shows the classic CM complaint: cannot find view for the DesignTimeCommandBarViewModel.
What's next?
Well, here's the solution I found: I'd be glad to hear about better ways or other suggestions.
Host MainView XAML specifies a design-time data-context pointing to a design-time version of the Main view-model which, by the way, does not inherit from the runtime version MainViewModel. ContentControl items are left untouched.
<Window x:Class="...MainView" ...
d:DataContext="{d:DesignInstance Type=fake:DesignTimeMainPanelViewModel, IsDesignTimeCreatable=True}"
cal:Bind.AtDesignTime="True">
<DockPanel ...>
<ContentControl x:Name="CommandBar" ... />
<ContentControl x:Name="ActiveItem" ... />
</DockPanel>
</Window>
DesignTimeMainPanelViewModel has the same public properties as MainPanelViewModel, has a default c'tor without dependencies and its c'tor sets the CommandBar property to a new instance of DesignTimeCommandBarViewModel:
public class DesignTimeMainPanelViewModel
{
public DesignTimeMainPanelViewModel()
{
CommandBar = new DesignTimeCommandBarViewModel();
ActiveItem = ...some instance here as well...;
}
public DesignTimeCommandBarViewModel CommandBar { get; private set; }
public IScreen ActiveItem { get; private set; }
}
DesignTimeCommandBarViewModel class is decorated with a custom Attribute having only one required parameter, the System.Type of the view associated with that view-model.
During bootstrap the code adds a new ViewLocator strategy to get the view Type from the view-model Type, by setting a new ViewLocator.LocateTypeForModelType.
The new locator function will try to find a view Type if the standard locator function cannot find one. Granted, it will look for the custom attribute on view-model Type, and if found that would be the returned view Type. Here's the gist of that:
Type viewType = _previousLocate(viewModelType, displayLocation, context);
if (viewType == null)
{
FakeViewAttribute fakeViewAttr = Attribute.GetCustomAttribute(viewModelType, typeof(FakeViewAttribute)) as FakeViewAttribute;
if (fakeViewAttr != null) viewType = fakeViewAttr.ViewType;
}
return viewType;

inheriting user control from a base class

I've done lots of searching and found lots of answers but for some reason it's not working for me. I have a VB app in WPF. I want some common code for user controls.
So I make a base class like this:
Public Class cU
Inherits UserControl
Public Value As Double
End Class
And a user control, the Xaml starts like this:
<UserControl x:Class="UserControl3"
So all I have to do, as far as I can see, is to change this to:
<local:cU x:Class="UserControl3"
But although no error is shown in the Xaml window, I get and error in the error list:
"local" is an undeclared prefix. Line 1. position 2.' XML is not valid
(by the way, when I did exactly this in winrt it worked fine)
I tried changing it to local to Controls and also putting cU in a namespace called local but it doesn't change.
Add your namespace in your XAML for your window tag or control tag (depends whichever you are using).
<Window x:Class="YourNamespace.YourClass"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:YourNamespace">
then you can use the <local:UserControl3 /> tag
the YourNamespace in your case would be WpfApplication1

Using derived class for UserControl - how to eliminate blue-lining in xaml editor?

I'm trying to use a C# class derived from UserControl as the base class for some xaml pages' layout root, so I can share some common functionality. I.e. the backing class is like:
public class BaseView : UserControl
{
// Some virtual functions I want in common ...
}
public class MyView : BaseView
{
// Overidden functions ...
}
The xaml file then references the class like:
<jt:BaseView x:Class="ns.MyView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:jt="clr-namespace:ns"
...>
</jt:BaseView>
This seems to work when running, but in the xaml editor, the code is all underlined with blue squiggly lines, with a fly-over message of something like "Cannot create instance of BaseView".
If I don't do this, and use UserControl in the xmal, I get errors because the partial class generated from the xaml then has the UserControl base class and not my custom base class.
How do I get the editor to know about my custom base class (i.e. get rid of the blue underlines)?
The most common cause for a design time "Cannot create instance..." sort of error is that the constructor of the element is doing something that doesn't make sense or is unavailable at design time.

Using Base classes in WPF

I have problem with base classes in WPF. I try to make a base class with some base elements, so that other windows can inherit these components. But all that i have, when I inherit base class is only empty window, without these elements. For better understanding i put my code here:
using XSoftArt.WPFengine;
namespace XSoftArt
{
public class WindowBase : Window
{
public WindowBase()
{
}
}
Code of the Windows, whitch inherits WindowBase:
namespace XSoftArt.WPFengine
{
public partial class NewAbility : WindowBase
{
public NewAbility()
{
base.ChildForm = this; InitializeComponent();
}
}
}
Or maybe someone can put an working example or link with implemented base classes in wpf?
Thanks
I don't think you really need to do what you are doing, but it is feasible. I think you are just forgetting to call the base class constructor.
using XSoftArt.WPFengine;
namespace XSoftArt
{
public class WindowBase : Window
{
//call base ctor
public WindowBase() : base()
{
}
}
}
You'll need to do this from your inherited classes as well:
namespace XSoftArt.WPFengine
{
public partial class NewAbility : WindowBase
{
public NewAbility() : base()
{
base.ChildForm = this; InitializeComponent();
}
}
}
And if you also have a XAML-defined view, you'll need to make sure your view is a WindowBase. To do this, change this:
<Window x:Class="MyApp.MyView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
...
>
<Grid>
</Grid>
</Window>
To this:
<local:WindowBase x:Class="MyApp.MyView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:XSoftArt;"
...
>
<Grid>
</Grid>
</local:WindowBase>
If you look at this class in Reflector you will see that the constructor calls the Window class's own "Initialize()" method, which sets a lot of things in motion. Specifically it appears to hook itself up to the Dispatcher, which is the work queue for all UI events.
In particular, you want to ensure that the InitializeComponent() method of the base class is called - this is the function that creates the controls that you defined in XAML.
Making a derived class is great if you want to inherit both controls and behaviour, but consider using Templates for a more flexible way of managing a common set of controls.
I don't think I'd ever use inheritance in WPF the way you're trying to use it.
I'll try and take a stab at answering your question. If I'm understanding you correctly, you're trying something like this:
You're creating a window that has both a XAML file and a code-behind.
You're adding "base elements" to the XAML for your window... I'm not sure what you mean by "base element", but I'm going to assume you mean you're adding UI elements to your window.
You're creating another window that "derives" from your first window in the code-behind, and the problem is that you're not seeing the UI elements on it from your "base" window.
If that is what you want to accomplish with WPF, I'd personally recommend against it, just because I'm personally not a fan of inheritance and have seen firsthand the dangers of letting inheritance get out of hand.
What you could try instead is organize your "base" UI elements into WPF UserControls. This tutorial might be able to guide you in the right direction. Good luck!

Resources