Friday 24 August 2012

Problems subclassing UserControl on WinRT

While trying to figure out how to add a generic mechanism for accelerators on buttons on my Win8 port of Bridge Stenographer I was faced with blank stares when asking about Keyboard Shortcuts

AutomationProperties.AccessKey="Number2" looked like the perfect property to add on my 2 button for instance, but I was disappointed to find out that nothing supported it.

In the end, I needed to have a base class that did some of the handling for my keyboard mapping to the access keys, as I don’t want to write that code over and over again (actually, I don’t want to debug and keep parallel copies up to date, but I digress).

So, what better way than a base class I thought.

So, here’s what I did.  I had my keyboard like control based on a UserControl.  Why not just change the base class to SpecializedUserControl like this:

public class SpecializedUserControl : UserControl
{

public SpecializedUserControl()
{
}

public void ExtraFunctionality()
{
}
}



Then, I can create a new user control, and base it on this new base class like this:


public sealed partial class MySpecializedUserControlInstance : SpecializedUserControl
{
public MySpecializedUserControlInstance()
{
this.InitializeComponent();
}
}


and declare it in XAML like this:

<local:SpecializedUserControl
x:Class="hoverbug.MySpecializedUserControlInstance"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:repro"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="400">

<Grid>
<Button>Sorry Charlie!</Button>
</Grid>
</local:SpecializedUserControl>


Interestingly, while writing this, I was disappointed to find that everything worked fine, and I wasn’t getting the error I got in my actual code.


Here’s how I instantiated the control on my page:


<local:MySpecializedUserControlInstance DataContext={Binding }" />


Not to be beaten (as it really didn’t appear to work in my code), I started porting across bits of my implementation, a feature of which was that I needed a property to attach to controls in my implementation that could hold a function to call when the AccessKey was pressed, so I did it like this in SpecializedUserControl:


public RoutedEventHandler KeyboardAction
{
get { return (RoutedEventHandler)GetValue(KeyboardActionProperty); }
set { SetValue(KeyboardActionProperty, value); }
}

// Using a DependencyProperty as the backing store for KeyboardAction. This enables animation, styling, binding, etc...
public static readonly DependencyProperty KeyboardActionProperty =
DependencyProperty.RegisterAttached("KeyboardAction", typeof(RoutedEventHandler), typeof(SpecializedUserControl),
new PropertyMetadata(null));


Now when I run the same program, I get this error:


oops


Anyone have any idea why adding a declaration of an attached property breaks it in this way?

2 comments:

  1. Where you able to solver this problem?

    ReplyDelete
  2. Yes, I put the attached property in a class of its own.

    ReplyDelete