Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Moving UIElements around in Metro

DZone's Guide to

Moving UIElements around in Metro

·
Free Resource

Moving stuff around in Metro

I'm playing with some code for the First Apps Contest, and since I had to dig some of this out, I thought maybe others might be interested. Was just thinking that ratting through documentation and trying to make stuff work is very reminiscent of WPF/E back in... holy crap... December 2006... doesn't seem like 5 years ago!

Where to start

I figured the easiest thing to do would be to put a circle on the screen and move it around. This has *got* to be easier than drag/drop, right?

Well yes it is, but as with most things you gotta figure out where to poke it to make it work, and of course I got involved in other stuff so I made it a bit tougher than I needed. I called this "Application3", and it's like the last one except I'm not doing a snap pane on this one.

ManipulationMode

Right off the bat I found out I had to get up close and personal with ManipulationMode. ManipulationMode is a property on the UIElement. I guess if you're a WP7 dev you're already familiar with this or could be. ManipulationModes is an enumeration and has the following values:
  1. None
  2. TranslateX
  3. TranslateY
  4. TranslateRailsX
  5. TranslateRailsY
  6. Rotate
  7. Scale
  8. TranslateInertia
  9. RotateInertia
  10. ScaleInertia
  11. All

I figured the easiest to play with would be TranslateX. I tried TranslateRailsX but um... is that a Ruby on Rails thing?? Nevermind... :)

There's a little setup to get the translation going, and the easiest is to show a xaml snippet:
<Ellipse x:Name="RedCircle"
         Grid.Row="1"
         Grid.Column="0"
         Width="50"
         Height="50"
         Fill="{Binding RedBrush}"
         ManipulationMode="{Binding ManipMode}"
         />
And the codebehind:
private TranslateTransform _dragTranslation;

public MainPage()
{
    InitializeComponent();
    _MyViewModel = new Application3ViewModel();
    DataContext = _MyViewModel;
    RedCircle.ManipulationDelta += new Windows.UI.Xaml.Input.ManipulationDeltaEventHandler(RedCircle_ManipulationDelta);
    _dragTranslation = new TranslateTransform();
    RedCircle.RenderTransform = _dragTranslation;
}

void RedCircle_ManipulationDelta(object sender, Windows.UI.Xaml.Input.ManipulationDeltaEventArgs e)
{
    _dragTranslation.X += e.DeltaManipulation.Translation.X;
    if (_dragTranslation.X < -680)
        _dragTranslation.X = -680;
    if (_dragTranslation.X > 680)
        _dragTranslation.X = 680;
}

The XAML is pretty simple... I'm just showing the Ellipse and the only real interesting thing in there is the ManipulationMode. Since the ManipulationMode is an enum and the documentation says "This enumeration is flagwise to facilitate setting multiple modes", I thought I'd give that a dance with a couple of the values comma-separated. Hmmm... that didn't work. Ok try it with the '+' operator... highly unlikely but what the heck... and of course no on that too. So... I ended up making it a value in the ViewModel so I could combine a couple of the values. As it turns out that ended up being a good idea because I set the value at run-time and could change the way it worked.

To get the translation going, we define a TranslateTransform value and new that badboy up in the constructor. Then set the RenderTransform parameter of the UIElement (the ellipse) to that.

We also need to set the ManipulationDelta of the UIElement with an event handler, and I just used the normal 'let VS do the heavy lifting for me' to create it, producing the "RedCircle_ManipulationDelta" handler you see above.

You need to set the translation value because every time you stop moving, the origin gets reset, so it's not a delta from where the app began. Thinking about that, I guess that's a good thing... it could get darned messy any other way.

I also found that I was going to probably want to clip the delta on that guy too. Once I added some Inertia (below), I was able to flip that sucker clean off the screen which wasn't overly useful as it turns out.

Moving the Circle left and right like this seemed a little 'laggy', and I tried removing some code thinking I was slowing it down, but I was developing this in a VHD on my i7 box, so that seemed unlikely. Messing around with the ManipulationModes, I came across Inertia and decided to play with that too.

TranslateInertia

Adding some Inertia to moving the circle around was dead simple... just OR in TranslateInertia on the ManipulationMode... woo hoo... that works nicely, and you can flick it across the screen... and if you're not 'catching' it at the edges... oops, where'd it go??

I've got more resolution on the big monitors but I figured if this circle starts off in the center, then I should be able to go +/- 680 before I lose it. Remember, the resolution is 1366X768 full screen, so 1366/2 is 683. Rounding that to 680, that puts the center of the circle just about at the point you'd be comfortable 'grabbing' it with your finger to dig it out of the crease. I made the circle with a diameter of 50 pixels... and that seems fine on the actual device.

To play with the Inertia a bit, I added a ToggleSwitch that I bound up to control the merging of TranslationX and TranslationInertia (or not). I also added a TextBlock to show the location on the screen. This wasn't necessary for this example, but it does prove the 680 and will be important to my entry in the contest.

Here's a screenshot of all 3 pieces of the UI:


The lag

There's still a lag... I compared it to moving a tile around on the home page and it's definitely laggy. I can move my finger faster than the circle can keep up. I thought maybe it was because I was running in VS, and didn't think of that while I was still running in the VHD, so I pulled the project onto the device, built, and deployed and it still feels laggy to me.

If somebody knows something I'm doing wrong, or not doing enough of, let me know and I'll post an add-on to this post. I'm not saying it's *really* annoying, it just seems a little slower on the up-take than I expected.

That's all for now

That's all for now... just a quick run-up of moving stuff around if you haven't had a chance to try it.

I've obviously left off lots of stuff like binding the ToggleButton and the TextBlock. I figured if you're reading this, you probably already know how to do that, and I don't want to annoy people. If however you'd like me to show that stuff let me know... I'm more than happy to talk about this in any detail you'd like.

Feel free to write and ask questions, and if you're blogging WinRT/Metro stuff please send me your links!

Now I've got to get back to working on my app for next week or I'll never get it done... and here I thought I might do two of them!
Topics:

Published at DZone with permission of Dave Campbell, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

THE DZONE NEWSLETTER

Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

X

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}