views:

146

answers:

3

All,

I have a simple class.

public class Container : UserControl
{
    public bool IsClickable { get; set; }
}

I have a class that extends this class.

public class ScrollingContainer : Container
{
    public void Draw()
    {

    }

    public void Update()
    {

    }
}

I have a custom class, that then extends ScrollingContainer.

public partial class MaskContainer : ScrollingContainer
{

    public MaskContainer()
    {
        InitializeComponent();
    }
}

XAML

<local:ScrollingContainer x:Class="Test.Types.MaskContainer"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:GameObjects;assembly=GameObjects"
    mc:Ignorable="d"
    >
</local:ScrollingContainer>

In my mainpage.xaml, I have the following.

<types:MaskContainer x:Name="maskContainer" Canvas.ZIndex="1" Width="Auto" Height="Auto">
       <Canvas x:Name="maskCanvas">
           <Button x:Name="button1" Content="test button"/>
       </Canvas>
</types:MaskContainer>

Why, at runtime, are both maskCanvas and button1 null? maskContainer is not null.

The inheritance should be straightforward here. Container inherits usercontrol. Scrollable container inherits container. Mask Container inherits scrollable container. Why am I losing the fucntionality of the original base class at this level? Is it incorrect to add the element (button1) to the maskcontainer inside of the main.xaml?

My end goal is to create a container that is reusable, but inherits all properties/methods that I've specified throughout the chain.

Any help is appreciated.

A: 

Verify that InitializeComponent() is truly being called before you check your variables.

These variables will certainly be null otherwise.

I have done the above with no issue, although normally used other controls like Grid, Canvas, etc.

Another thing to check: does the Container class have Xaml? I do not believe you can subclass and use Xaml on a class that already uses Xaml.

Jonathan.Peppers
I can 100% verify that InitalizeComponent is being called. The container class does not have xaml. The container class is stated as above. A very simple class with a simple property.What I'm attempting to do is to define a usercontrol with additional properties that I've defined in another class. What I want to do is to have the ability to create this custom control, then add elements into it from another xaml page.
csciguy
In your Xaml where you declare local:ScrollingContainer, you declare it to have no children. Yet in your main Page/Window, you add children to it. I don't think Xaml supports this, if you want to put children in your custom control, you need to do so in it's Xaml rather than from the main Page or Window. If this is an issue for you, there probably is a better way to go about setting this up (better design choice). This is why some controls like Border, etc. have a singular Child property that can be set from a main Page or Window, but this may/may not be the best choice for your scenario.
Jonathan.Peppers
See, my idea is to create a control that another group of designers would not be locked down to. I wanted to extend usercontrol, but to add my own elements, then allow the designers to add children to that control from the main page (or other design page). Would I run in to this same problem if I extended, say Canvas, instead of UserControl?
csciguy
I've extended Panel instead of canvas now, and can add basic controls into this canvas, however, I cannot add any other usercontrols that I have made into this canvas. All are still coming up null at runtime. Any ideas?
csciguy
I tried doing something similar in VS 2010 RC, and it gives me a compiler error: Cannot set Name attribute value 'maskCanvas' on element 'Canvas'. 'Canvas' is under the scope of element 'MaskContainer', which already had a name registered when it was defined in another scope. It think this is where your issue lies. Does a Style and maybe a couple attached properties not better suit your purposes?
Jonathan.Peppers
I ended up just making a custom canvas class that suited my needs (for now). It's a little more close-ended, but that's okay for the time being. I made it a bullet point for a future release to investigate further. Thanks for the help though.
csciguy
+1  A: 

The problem is, MaskContainer has an attached XAML file, which makes the WPF codegen generate a class that implements System.Windows.Markup.IComponentConnector. And when a control implements that interface, it receives a whole new quality: it becomes a naming scope root. Which means that inside such a control, there is a whole separate naming space. Control names outside do not conflict with inside ones.

In this particular case, that means that both maskCanvas and button1 are not visible from within mainpage by name, but are visible from within MaskContainer instead.

In fact, I'm very surprised that you've even managed to get this compiled somehow. From my experience, if you try this trick with Visual Studio, it would complain about maskCanvas being "under scope of element MaskContainer". Do you use command-line compilation by any chance?

Ok, so enough blah-blah-blah already.

What's the solution? Simply remove XAML file from MaskContainer. That will get rid of autogenerated IComponentConnector implementation, and everything will work as you expect it to.

Fyodor Soikin
A: 

I actually found out that under the current RC, you cannot extend a usercontrol like I was trying to do. What I ended up doing to solve the problem (for now) was to dumb down the expectations of the system and to extend Canvas instead of the usercontrol itself. I would have preferred to have extended the usercontrol, but oh well. This will suffice for now.

csciguy