Solved

Using code from base class at design time with WPF

Posted on 2014-09-18
6
251 Views
Last Modified: 2014-11-27
Here’s an interesting problem:

      I want to use a custom window as a base for other windows in my project. I’ve tried this before and learned the lesson that you can have visual inheritance with XAML. So I decided I would define the base class via code, since I don’t have that much I need to add, but I’m running into a problem.
      Here’s my scenario. First I have my base class:

Public Class TheBase
    Inherits Window

    Public Sub New()
        Dim MainGrid As New Grid

        Content = MainGrid

        MainGrid.Children.Add(New TextBlock With {.Text = "This is a test"})
    End Sub
End Class

Open in new window


      Then I have the class that inherits it:

Public Class TheFinalWindow

End Class

Open in new window


      The XAML for it is:

<MyNS:TheBase x:Class="TheFinalWindow"
    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"
    xmlns:MyNS="clr-namespace:MyNamespace">

</MyNS:TheBase>

Open in new window


      When I run the code to show an instance of TheFinalWindow, I see the TextBlock which says “This is a test”, but when I open up TheFinalWindow in design mode, it doesn’t appear. In my actual project, I’m trying to add a container to “TheBase” and then put controls into it through “TheFinalWindow”, but I haven’t gotten any farther than this. I definitely need design time support for this so I can make “TheFinalWindow” without having to run the code every three seconds to see what I’m doing.
      What can I do to fix this?
0
Comment
Question by:BROOKLYN1950
  • 3
  • 2
6 Comments
 
LVL 25

Expert Comment

by:apeter
ID: 40335637
You have to override some of the methods in your custom window. Hope this links helps you, http://blog.magnusmontin.net/2013/03/16/how-to-create-a-custom-window-in-wpf/
0
 

Author Comment

by:BROOKLYN1950
ID: 40348010
Okay, thanks to apeter I seem to be onto something. I followed his link and learned quite a bit. It seems like I should be able to do this through control templates, since it doesn't cause the error of inheriting from a class defined in XAML.
I've been looking into default control templates for custom classes (i.e. defining a style in Themes\Generic.xaml). So far the best example I could find is this:

http://svetoslavsavov.blogspot.com/2009/09/user-control-inheritance-in-wpf.html

In his second example ("Variant 2" as he calls it), he creates a custom control with a style in Generic.xaml and then inherits from it to make a user control which he then adds content to. I downloaded the source code and confirmed that everything works in the designer as well as at runtime.
The problem is that when I try to do the same thing with a window, it doesn't show it in the designer. I've attached a modified version of his source code in which I try to show his inherited control inside my inherited window. The style defined in Generic.xaml doesn't get applied to the design time window but it works fine at run time.

Any ideas on how to make the window work like the user control does?
0
 
LVL 25

Expert Comment

by:apeter
ID: 40375726
Hope these link gives you some idea. https://wpfwindow.codeplex.com. and this as well, http://3water.wordpress.com/2013/02/16/metro-style-window-in-wpf/

What you are trying to customise your window ?
0
 

Accepted Solution

by:
BROOKLYN1950 earned 0 total points
ID: 40460074
Okay, so I finally figured it out through trial and error and some lucky ideas. Here's what I had to do:

First off I had to define a custom Style with ControlTemplate in my "Generic.xaml" file. To do this I used Blend to get the default ControlTemplate for Window and then modified it to fit my needs (I added a Button on the bottom as well as a few other things).

I then added a block like this to my "TheBase" class:

Public Shared Sub New()
    DefaultStyleKeyProperty.OverrideMetadata(GetType(TheBase), New FrameworkPropertyMetadata(GetType(TheBase)))
End Sub

Open in new window


I also overrode the OnApplyTemplate method to get access to the custom elements I added in the ControlTemplate (i.e. the Button I mentioned above). I then added any functionality I wanted in all my "child" classes into my "TheBase" class (i.e. what I wanted the button to do when it was clicked).

So in the end my base class looked like this:

Public Class TheBase
    Inherits Window

    Private _MyButton As Button
    Friend ReadOnly Property MyButton As Button
        Get
            Return _MyButton
        End Get
    End Property

    Public Shared Sub New()
        DefaultStyleKeyProperty.OverrideMetadata(GetType(TheBase), New FrameworkPropertyMetadata(GetType(TheBase)))
    End Sub

    Public Overrides Sub OnApplyTemplate()
        MyBase.OnApplyTemplate()

        _MyButton = GetTemplateChild("PART_MyButton")
    End Sub

    'Custom window logic here

End Class

Open in new window


Next I went on to making my first "child" class. I added a new Window to my project, but changed the beginning and ending tags from "Window" to "MyNS:TheBase".

Now here's the trick that got it to work at design time. I had to add this to my "child" class:

    <Window.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="/MyNS;component/Themes/Generic.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Window.Resources>

Open in new window


Once I added that, everything work at both design time and runtime.

Note that I did not have to override any existing Window logic (such as the Minimize and Maximize buttons) as had been suggested in some of the links above.

I hope this helps out anyone else who has this problem, even though it seems to be a very rare need.
0
 

Author Closing Comment

by:BROOKLYN1950
ID: 40468679
I was the one who ultimately got a solution to my problem. Though some of the comments did help point me in the right direction, I had to piece everything together and mess around until I actually got it working.
0

Featured Post

Master Your Team's Linux and Cloud Stack!

The average business loses $13.5M per year to ineffective training (per 1,000 employees). Keep ahead of the competition and combine in-person quality with online cost and flexibility by training with Linux Academy.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

NTFS file system has been developed by Microsoft that is widely used by Windows NT operating system and its advanced versions. It is the mostly used over FAT file system as it provides superior features like reliability, security, storage, efficienc…
Sometimes drives fill up and we don't know why.  If you don't understand the best way to use the tools available, you may end up being stumped as to why your drive says it's not full when you have no space left!  Here's how you can find out...
Windows 8 came with a dramatically different user interface known as Metro. Notably missing from that interface was a Start button and Start Menu. Microsoft responded to negative user feedback of the Metro interface, bringing back the Start button a…
With the advent of Windows 10, Microsoft is pushing a Get Windows 10 icon into the notification area (system tray) of qualifying computers. There are many reasons for wanting to remove this icon. This two-part Experts Exchange video Micro Tutorial s…

831 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question