First of all you need to install Caliburn Micro in your UWP project. You can follow the step described in this article.
Now you have a new project with a MainView.xaml and a MainViewModel.cs in theis folders.
To have a sample view where operate, open the MainView.xaml and build a grid with one or more Border in the view. To best perform Caliburn Micro framework, is better have an abstract base class to implement in the view model
[code lang=”c-sharp”]
public abstract class ViewModelBase : Screen, IViewAware
{
public readonly INavigationService navigationService;
public static object Parameters { get; private set; }
protected ViewModelBase(INavigationService navigationService)
{
this.navigationService = navigationService;
navigationService.Navigating += NavigationService_Navigating;
}
private void NavigationService_Navigating(object sender, NavigatingCancelEventArgs e)
{
Parameters = e.Parameter;
}
public void GoBack()
{
navigationService.GoBack();
}
public bool CanGoBack
{
get
{
return navigationService.CanGoBack;
}
}
}
[/code]
This abstract class have to be implemented in our ViewModel
[code lang=”c-sharp”]
public class MainViewModel : ViewModelBase
{
#region Properties and Private fields
static WinRTContainer container = (Application.Current as App).container;
private readonly INavigationService _navigationService;
private readonly IEventAggregator _eventAggregator;
#endregion
#region Constructors
public MainViewModel(INavigationService navigationService) : base(navigationService)
{
_eventAggregator = container.GetInstance<IEventAggregator>();
_eventAggregator.Subscribe(this);
_navigationService = navigationService;
}
#endregion
}
[/code]
Now we can begin to build a simple view with some Borders to drag. To have a simple view to manipulate, I’ve add four square Borders, with a textblock inside, to drag.
At this point need to add the event to manipulate.
Pointers
in the UWP there is a new concept linked to the input device ad mouse, touch, controllers (for XBox)… etc. Manage these large quantity of devices, is very complicate. But the new UWP introduced a new concept: the “Pointers”. The pointers manages all kind of devices with simple common interfaces.
But what are the interested events for the drag? here the list with the explains.
- PointerMoved: is the event that allows us to get the informations about the movement of the pointer on the control
- PointerPressed: is the event that allows us to get the information when the pointer is pressed on the control
- PointerReleased: is the event that allows us to get information when the pointer is released on the control
here the code vot a single Border that I’ve used
[code lang=”xml”]<Border x:Name="buttonA" HorizontalAlignment="Left" Margin="86,95,0,0" VerticalAlignment="Top" Height="80" Width="80" cal:Message.Attach="[Event PointerReleased] = [Action PointerReleased()]; [Event PointerMoved] = [Action PointerMoved($source,$eventArgs)]; [Event PointerPressed] = [Action buttonPointerPressed($source,$eventArgs)]" Background="#FFC8C8C8" >
<TextBlock Text="1" HorizontalAlignment="Center" VerticalAlignment="Center" Height="28" Margin="0" Width="20" MinWidth="4" MinHeight="1" SelectionHighlightColor="{x:Null}" />
</Border>[/code]
Take note to the multi caliburn events attached on the single control.
And now in the ViewModel add five variables:
[code lang=”xml”]double xPos = 0;
double yPos = 0;
double xGap = 0;
double yGap = 0;
bool press = false; [/code]
And the callbacks for each events:
[code lang=”c-sharp”]private void PointerReleased()
{
press = false;
}
private void buttonPointerPressed(object sender, PointerRoutedEventArgs e)
{
bool _hasCapture = ((Border)sender).CapturePointer(e.Pointer);
var s = _hasCapture;
var b = (Border)sender;
xPos = b.Margin.Left;
yPos = b.Margin.Right;
press = true;
}
private void PointerMoved(object sender, PointerRoutedEventArgs e)
{
var v = GetView() as MainView;
var b = (Border)sender;
if (press)
{
var p = e.GetCurrentPoint(v.MainGrid);
xPos = p.Position.X – xGap – (b.ActualHeight / 2);
yPos = p.Position.Y – yGap – (b.ActualWidth / 2);
b.Margin = new Thickness(xPos, yPos, b.Margin.Right, b.Margin.Bottom);
}
}
[/code]
Enjoy and stay tuned!