dimanche 4 décembre 2016

Webview Edge vs IE, ScriptNotify working on WP 8.1 but not Windows 10, when the Edge Webview throws you a little curve ball and how to fix it [HTML,C#]

I need to use a Webview in my app so that the application could communicate with my Webview and vise versa.  In my previous article I explained how you can call JavaScript methods from an app [Here], but what happens when the Webview wants to send you some kind of information.

You will tell me, well just use:

window.external.notify(message); 


 and you are good to go! Or use like you did in your previous article:

window.SCObject.getMyMethod();    

However I had the constraint that I am not the one developing the Html and JavaScript that is being called in the Webview, and thus had to work with what I was given.

What you must now is that for Windows Phone 8.1 the Webview uses IE and for Windows 10 the Webview uses Edge.

So, lets head back to my story, on Window Phone 8.1 and Windows 8.1 when I executed a html page in my Webview that had:


function SendTestNotify() {
   if(typeof window.external.notify !== 'undefined')
   {
     window.external.notify('test info');
   }
}           

My Webview would send me back events through ScriptNotify.  However on Windows 10 this code will not send you anything...

So going back to the basic I test this on Windows Phone 8.1

 window.external.notify(typeof window.external.notify);

And got a 'undefined' oddly when you test this on Windows 10 you also get  'undefined' ... So now you can start thinking that I messed up somewhere, however I have found out that trying this code on Windows Phone and on Windows 10 will also not give you the same result:

 window.external.notify(typeof window.external.notify !== 'undefined');

On Windows Phone 8.1 this will send you true and on Windows 10 false.  So I have concluded that the Windows 10 Webview is weird. It can tell me the type of window.external.notify however the JavaScript doesn't seem to be able to detect what typeof it is.

All in all, there will need to be specific code for Windows 10 because its Webview does not behave like the other Webview  on windows 8.x.  Thus this part of the JavaScript code does not work as expected on Windows 10:

if(typeof window.external.notify !== 'undefined') 

Happy Coding,

lundi 15 août 2016

Communicating back and forth with a WebView in a UWP application using AddWebAllowedObject or ScriptNotify [HTML,C#]

There are many solutions to the problem, in this article I will try and explain why I I think that using a Windows Runtime Component library is better then using a window.external.notify to try and communicate with your WebView in a UWP application.


Using window.external.notify() and ScriptNotify 

Trying to get your application and you HTML page to communicate with each other is never easy and the WebView in UWP doesn't seem to really help us out (IMO of course).  If you try to use window.external.notify(in your WebView not only do you need the link to be in HTTPS but also need to declare the https link(s) in the manifest of your application and need to have access to the html page to add IE/EDGE specific code.

FYI: the you can only declare HTTPS links in Content URi that is why you need your webview link to be HTTPS.

And so your Content URIs might look like this for example:


Also using window.external.notify would force us to have to listen to the ScriptNotify event, and parse the value to know what method we need to call, it would look something like this:

public MainPage()
{
       this.InitializeComponent();
       string src = " https://XXXXXXXXX.com/";
       webView.Navigate(new Uri(src));
       webView.ScriptNotify += webView_ScriptNotify;
}


void webView_ScriptNotify(object sender, NotifyEventArgs e)
{
    var elementPassed =  e.Value; //need to parse this
    
    // now we need to parse our value to know what method needs to be called
    string elementName = elementPassed[0];
    string elementValue = elementPassed[1];
}

For me this was not an option, I wanted to be able to call my C# methods from within my html app.


Looking at MSDN we can see that WebView.AddWebAllowedObject method will Adds a ''native Windows Runtime object as a global parameter to the top level document inside of a WebView''.  This sounds EXACTLY like what I want: to be able to call C# code from within my local html page using javascript!

Creating the Windows Runtime Component library to communicate with the WebView

So let get started, first we need to create a new project Windows Runtime Component library.  For some weird reason you need to add create this in new WRC library and mark this class this  [AllowForWeb] so that you can bypass the WebView security subsystem... (weird but I guess MS must have a good reason for doing this?).

Here is what my Windows Runtime Component library looks like, it only have one class called HtmlCommunicator that is a public sealed class and the attribute AllowForWeb.

using System;
using Windows.ApplicationModel;
using Windows.Foundation.Metadata;


namespace MainApp.Connector
{
    [AllowForWeb]
    public sealed class HtmlCommunicator
    {
        public void getHtmlSpecificEvent()
        {
          // do something else
        }

        public string getAppVersion()
        {
            PackageVersion version = Package.Current.Id.Version;
            return String.Format("{0}.{1}.{2}.{3}",
                                 version.Major, version.Minor, version.Build, version.Revision);
        }
    }
}


Getting the Html page to communicate with our C# code

Lets start with the our main page of our XAML app, I will add a simple WebView to the app:

<Page
    x:Class="MainApp.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:MainApp"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <WebView VerticalAlignment="Bottom" 
             NavigationStarting="HtmlWebView_NavigationStarting"
             x:Name="HtmlWebView"
             Margin="0"
             Height="146"
             />
    </Grid>
</Page>

Now for the cs part of the page, we will now get our Windows Runtime Component library hocked onto the WebView .  We will need to call AddWebAllowedObject  every time the WebView navigates to a new web page, by doing this we can access the native objects that are in our HtmlCommunicator class:


        private HtmlCommunicator communicationWinRT = new HtmlCommunicator();


        private void HtmlWebView_NavigationStarting(WebView sender, WebViewNavigationStartingEventArgs args)
        {
            this.HtmlWebView.AddWebAllowedObject("SCObject", communicationWinRT);
        }

Lastly we create our html page (because I am lazy I will host the html page inside the application) with 2 methods that will call 2 different c# methods.

<!DOCTYPE html>

<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="utf-8" />
    <title></title>
</head>
<body>

    <button style="width: 200px; height: 60px; font-size: x-large" onclick="HtmlPageEvent()">Get Event</button>

    <button style="width: 250px; height: 60px; font-size: x-large" onclick="HtmlGetAppVersion()">Get App Version</button>

    <script type="text/javascript">
        function HtmlPageEvent() {
            window.SCObject.getHtmlSpecificEvent();
        }

        function HtmlGetAppVersion() {
            var version = window.SCObject.getAppVersion();
            alert(version);
        }
    </script>

</body>
</html>

And there you have, you can now call C# methods from within your local HTML page in you UWP application.

I truly believe that being able to call a specific method from within out HTML page is a better solution then using a window.external.notify() and having to catch the event using ScriptNotify to the route the event and parameters to the correct method.

You can find my solution here
Happy coding.



mercredi 1 juin 2016

Customizing Template 10 page header bar by editing its styles [Template10,XAML,UWP]

In this very short article we will look at how to customize your PageHeader in the Template 10 Control.

In the example we will remove the three dots that allow you to show the name of the button or show the secondary buttons in the header bar.

Or in other words we will go from this:


To this :

To keep things very simple I have just cloned the default Hamburger sample app from template 10 which can be found here under  https://github.com/Windows-XAML/Template10/tree/master/Templates%20(Project)/Hamburger

Next we need to find the default styles for the PageHeader and the PageHeaderButton, the two different styles can be found here under https://github.com/Windows-XAML/Template10/blob/master/Template10%20(Library)/Themes/PageHeader.xaml

What you will need to do is look under the style named PageHeader and under each VisualTransition you will have  ObjectAnimationUsingKeyFrames elements that is targeting MoreButton and should comment out this Element.

Here is an example of what one of the ObjectAnimationUsingKeyFrames look like:


<ObjectAnimationUsingKeyFrames 
      Storyboard.TargetName="MoreButton" 
      Storyboard.TargetProperty="VerticalAlignment">
     <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Stretch" />
</ObjectAnimationUsingKeyFrames>

You will need to comment out element that reference MoreButton about 34 times, once you have done this you should not be seeing the three anymore congratulation!

Here is the Link to the sample project.
Happy coding.










mercredi 11 mai 2016

How to draw an Arc using a Timer for UWP apps to make it look like a loader (Works for Mobile/Desktop/Xbox) [C#,XAML]

What I wanted to do was to create a circle that draws itself and that looks like its going to load something, and because a picture is better then a 1000 words here is what I mean:



I did not create the files Arc and ArcHelper this gentleman did : https://github.com/arek-kubiak/ArcControl/tree/master

And thus has allowed me to gain some time as I wont need to create an ArcControl I can just use his repo, here is what the initial Arc Control looks like:


What I currently have:

  • a Circle that can drawn using the percentage value. 


What I will need to do:

  • Increase that percentage value to make it look like it is drawing itself 
  • Have an event fired when the circle percentage reach's 100% (so that i can do something with it afterwards)
Here is what my UserControl looks like:


  <arcControl:Arc x:Name="MyArcLoader" 
                   Radius="65" 
                   Fill="White" 
                   PercentValue="1" 
                   Thickness="5" 
                   Margin="10" />

As you can see my PercentValue starts at 1 (it could be 0 also).

Now once our UserControl has loaded all we need to is add a DispatcherTimer set the Interval and increase the Percentage Value by the amount that we want.

For my case, I have set set the Interval to 5 milliseconds and will be increasing the Percentage value by 0.45.  Here is my UserControl:


 public sealed partial class LoadingInUserControl : UserControl
    {
        static DispatcherTimer Timer;
        public event Action OnAutoNextTick;
      
        public LoadingInUserControl()
        {
            this.InitializeComponent();
            Loaded += MainPage_Loaded;
        }

        private void MainPage_Loaded(object sender, RoutedEventArgs e)
        {
            //step up timer
            Timer = new DispatcherTimer();
            Timer.Interval = TimeSpan.FromMilliseconds(5);
            Timer.Tick += Timer_Tick;
            Timer.Start();
        }

        private void Timer_Tick(object sender, object e)
        {
            if (MyArcLoader.PercentValue < 100)
            {
                MyArcLoader.PercentValue = MyArcLoader.PercentValue + .45;
                MyArcLoader.UpdateLayout();
            }
            else
            {
                OnAutoNextTick?.Invoke();
                Dispose();
            }
        }

        public void Dispose()
        {
            if (Timer == null)
            {
                return;
            }
            Timer.Stop();
            Timer.Tick -= Timer_Tick;
            Timer = null;
        }
    }

My OnAutoNextTick action allows me to know when the Arc has hit that 100 percent value outside of the usercontrol.

Add this is what the final control looks like:



If you have an questions don't hesitate to ask!
Happy coding





mercredi 13 avril 2016

Dailymotion presentation on migrating its Windows 10 application to Xbox One.


Presentation for Microsoft hackathon in Europe 2016 about Dailymotion migrating its Windows 10 application to Xbox One.

You can find all of my code and gist here: https://gist.github.com/Delaire/














vendredi 25 mars 2016

Using adaptive triggers to build an application that can run on multiple Windows 10 platforms (Mobile/Desktop) XAML

Building applications is hard, and making them compatible on multiple platforms is a headache. You can either create multiple apps for specific platforms and use TargetDeviceFamily like in this tutorial or use AdaptiveTriggers so that you can adapt your view to the screen of a device.
On the Dailymotion Windows 10 application we wanted to use the same views on Mobile and Desktop devices. This is where adaptive triggers come to the rescue.
In this tutorial I will explain how to use AdaptiveTriggers to resize the width of our ItemTemplate inside a Gridview, when the application changes size. When the application is reduced to a certain size, I want the ItemTemplate that has a fixed size (300 pixels) to take up the whole width of the page.
Because a Gif is better then a 1000 words, this is the effect that I would like:
Adaptive cats

This tutorial will cover:

  1. What are AdaptiveTriggers
  2. How to use AdaptiveTriggers on a DataTemplate

What are Adaptive Triggers

Quick description: adaptive triggers allow you to create a rule (or set of rules) that can trigger a change in the visual state of your application (you can change the Size/Color/Visibility/etc of an element for example). This can allow you to resize elements without having to listen to the Window.SizeChanged event (that's AWESOME! let's do this!).
A lot more information can be found on MSDN here

How to use adaptive triggers on Items inside a GridView

The trick to using adaptive triggers inside a GridView is to implement it inside theDataTemplate, however, you can't create a
 <VisualStateManager.VisualStateGroups />
inside a resource file, so how is this possible?
You need to create a UserControl that you reference in your DataTemplate like this:
 <DataTemplate>
     <controls:AdaptiveCatItem />
 </DataTemplate>
And you set your VisualStateManager in the UserControl.
Here is an example on my User Control:
<UserControl x:Class="AdaptiveTriggers.Win10.Controls.AdaptiveCatItem"             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">  
    <Grid x:Name="TemplateRoot"
          Height="250"
          Width="300"
          HorizontalAlignment="Stretch"
          Margin="2"
          VerticalAlignment="Top">        
          <VisualStateManager.VisualStateGroups>
            <VisualStateGroup x:Name="VisualStateGroup">
                <VisualState x:Name="VisualStateNarrow">
                    <VisualState.StateTriggers>
                        <AdaptiveTrigger x:Name="VisualStateNarrowTrigger" MinWindowWidth="0" />                              
          </VisualState.StateTriggers>
                    <VisualState.Setters>
                        <Setter Target="TemplateRoot.Width" Value="Auto" />
                    </VisualState.Setters>
                </VisualState>
                <VisualState x:Name="VisualStateNormal">
                    <VisualState.StateTriggers>
                        <AdaptiveTrigger x:Name="VisualStateNormalTrigger" MinWindowWidth="521" />
                    </VisualState.StateTriggers>
                    <VisualState.Setters>
                        <Setter Target="TemplateRoot.Width" Value="300" />
                    </VisualState.Setters>
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>

        <Grid.RowDefinitions>
            <RowDefinition Height="190" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>   

        <Image Grid.Row="0"
               HorizontalAlignment="Center"
               Source="{Binding ThumbnailUri}"
               Stretch="UniformToFill" />

        <Grid Grid.Row="1"
              HorizontalAlignment="Stretch"
              VerticalAlignment="Top"
              Background="Transparent">
            <TextBlock Grid.Row="0"
                       Margin="5,5,5,5"
                       Text="{Binding Title,
                       FallbackValue='This is the cat image of the year'}"
                       />
        </Grid>
    </Grid>    
</UserControl>  
My VisualStateManager has two important AdaptiveTriggers. The first one is named VisualStateNarrowTrigger with a MinWindowWidth of 0 and another one named VisualStateNormalTrigger with a MinWindowWidth of 521. In this example, VisualStateNormalTrigger is the most important one.
What VisualStateNormalTrigger does is when the application is larger than 521 pixels then my items in the GridView have a width of 300. When my application width is smaller than 521 pixels the trigger VisualStateNarrowTrigger is fired and the width of my items in the GridView are set to Auto (which means that it will take up as much space as it can).
Going back to my VisualStateManager, here are the two important parts:
  • As mentioned above, VisualState allows me to set the width to auto on my grid element named TemplateRoot, when the application has a width of 0 pixels or more:
 <VisualState.StateTriggers>
     <AdaptiveTrigger x:Name="VisualStateNarrowTrigger" MinWindowWidth="0" />
 </VisualState.StateTriggers>
 <VisualState.Setters>
    <Setter Target="TemplateRoot.Width" Value="Auto" />
 </VisualState.Setters>
  • This VisualState allows me to set the Width to 300 on my grid element named TemplateRoot when the width of my application is 521 pixel or more:
   <VisualState.StateTriggers>
      <AdaptiveTrigger x:Name="VisualStateNormalTrigger" MinWindowWidth="521" />
   </VisualState.StateTriggers>
   <VisualState.Setters>
       <Setter Target="TemplateRoot.Width" Value="300" />
   </VisualState.Setters>
And there you have it, you can now resize the items that are inside your GridView when your application is resized without using any C# codeAdaptive cats
All of the code can be found on Github here
This piece of XAML code is what has allowed our Dailymotion application to be both Mobile and Tablet compatible without havving to code two appsDownload our sample here and give it a try!
Happy Coding =)

PS: as you can guess I like cats ^^

vendredi 4 mars 2016

Using an adaptive trigger to detect what platform your application is running on (Windows 10, XAML, C#)

I recently had issues with not knowing what platform my application was running on and wanted to have a specific UI depending on the platform and not depending on the size of the window.

Previously I had created a simple class (here) that allows you very simply detect what platform you are running on.  Next all I needed was to create a custom state trigger based on my previous class and we will be able to detect whether we are running on a Mobile, Tablet or Xbox platform.

First we need to create class that inherits from StateTriggerBase as follows:

namespace Win10.StateTriggers
{
    //you will also need https://gist.github.com/Delaire/37cbe07738df34bfd5e8
    public class DeviceFamilyStateTrigger : StateTriggerBase
    {
        private static DeviceTypeEnum deviceFamily;

        static DeviceFamilyStateTrigger()
        {
            deviceFamily = DeviceTypeHelper.GetDeviceType();
        }

        public DeviceTypeEnum DeviceFamily
        {
            get { return (DeviceTypeEnum)GetValue(DeviceFamilyProperty); }
            set { SetValue(DeviceFamilyProperty, value); }
        }

        public static readonly DependencyProperty DeviceFamilyProperty =
            DependencyProperty.Register("DeviceFamily", typeof(DeviceTypeEnum), typeof(DeviceFamilyStateTrigger),
            new PropertyMetadata(DeviceTypeEnum.Other, OnDeviceTypePropertyChanged));

        private static void OnDeviceTypePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var obj = (DeviceFamilyStateTrigger)d;
            var val = (DeviceTypeEnum)e.NewValue;

            if (deviceFamily == val)
                obj.IsActive = true;
        }

        private bool m_IsActive;

        public bool IsActive
        {
            get { return m_IsActive; }
            private set
            {
                if (m_IsActive != value)
                {
                    m_IsActive = value;
                    base.SetActive(value);
                    if (IsActiveChanged != null)
                        IsActiveChanged(this, EventArgs.Empty);
                }
            }
        }

        public event EventHandler IsActiveChanged;
    }   
}

what we have here is that we get the current platform type and check to see if our DeviceFamily property is of the same value, if so then the trigger will return an IsActive to true.

Here is how to use it in your XAML code: (the data in here is fake of course)

<VisualStateManager.VisualStateGroups>
   <VisualStateGroup x:Name="AbcVisualStateGroup">
      <VisualState x:Name="AbcVisualStateNarrow">
          <VisualState.StateTriggers>
     <AdaptiveTrigger x:Name="AbcVisualStateNarrowTrigger" MinWindowWidth="100" />
   </VisualState.StateTriggers>
   <VisualState.Setters>
     <Setter Target="AbcControl.(UIElement.Visibility)" Value="Collapsed" />
   </VisualState.Setters>
     </VisualState>
  <VisualState x:Name="AbcVisualStateNormal">
     <VisualState.StateTriggers>
       <AdaptiveTrigger x:Name="AbcVisualStateNormalTrigger" MinWindowWidth="400" />
       <stateTriggers:DeviceFamilyStateTrigger DeviceFamily="Xbox" />
         </VisualState.StateTriggers>
  <VisualState.Setters>
    <Setter Target="AbcControl.(UIElement.Visibility)" Value="Visible" />
 </VisualState.Setters>
      </VisualState>
    </VisualStateGroup>
</VisualStateManager.VisualStateGroups>

What we can see here is that the state AbcVisualStateNormal will be called when we have MinWindowWidth="400"  or when DeviceFamily="Xbox". 

As you can see it was quite simple =)

Here are my 2 classes that you will need DeviceTypeHelper.cs and DeviceFamilyStateTrigger.cs


Happy coding!


jeudi 4 février 2016

How to find the device platform/type your Windows 10 application is running on (Desktop/Mobile/Universal/Team/Xbox)

I wanted to be able to detect on what kind of device my UWP application was running and did not wanted to reinvent the wheel, I looked at what Wagonli did here and adapted it to my needs.

All I needed this helper to do was to tell me whether my application was running on a Phone or Tablet device.  For me I don't really fined it necessary to need to differentiate Desktop and Tablet for me its the same thing( for my UWP apps).

And for the fun i added Xbox so that you can also check if your appliction is running on a Windows 10 Xbox (Thanks @RudyHuyn)

Thus I ended up with this:

public static class DeviceTypeHelper
{
    public static DeviceTypeEnum GetDeviceType()
    {
        switch (Windows.System.Profile.AnalyticsInfo.VersionInfo.DeviceFamily)
        {
            case "Windows.Desktop":
                return DeviceTypeEnum.Tablet;
            case "Windows.Mobile":
                return DeviceTypeEnum.Phone;
            case "Windows.Universal":
                return DeviceTypeEnum.IoT;
            case "Windows.Team":
                return DeviceTypeEnum.SurfaceHub;
            case "Windows.Xbox":
                return DeviceTypeEnum.Xbox;
            default:
                return DeviceTypeEnum.Other;
        }
    }
}

public enum DeviceTypeEnum
{
    Phone,
    Tablet,
    IoT,
    Xbox,
    SurfaceHub,
    Other
}

My gist: https://gist.github.com/Delaire/37cbe07738df34bfd5e8
Original gist: https://gist.github.com/wagonli/40d8a31bd0d6f0dd7a5d

lundi 25 janvier 2016

Deploying your Universal Application (UWP) on only one platform/device type using TargetDeviceFamily

What I want to do is deploy my Universal Application (UWP) on a single platform (Desktop in my case) at first, then afterward deploy it on another device family. You can find all the device familes Here.

When you create a UWP application find the file called Package.appxmanifest open it with notepad, and by default under Dependencies you should see this:


 <Dependencies>
    <TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.0.0" MaxVersionTested="10.0.0.0" />
  </Dependencies>

Which is probably topically what you would want to, which is to have TargetDeviceFamily Name="Windows.Universal" which means that it targets all of the Windows 10 devices!

However in my case I just want to target the desktop app, thus I need to set  TargetDeviceFamily Name to Windows.Desktop as follow:

 <Dependencies>
    <!--<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.0.0" MaxVersionTested="10.0.0.0" />-->
    <TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.0.0" MaxVersionTested="10.0.0.0" />
  </Dependencies>

And there you have it.

Targeting different platform type:


Here are the different Names that you can set TargetDeviceFamily, so that it only works on:
  • Mobile
 <Dependencies>
    <TargetDeviceFamily Name="Windows.Mobile" MinVersion="10.0.0.0" MaxVersionTested="10.0.0.0" />
  </Dependencies>

  • Desktop
 <Dependencies>
    <TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.0.0" MaxVersionTested="10.0.0.0" />
  </Dependencies>


  • Xbox
 <Dependencies>
    <TargetDeviceFamily Name="Windows.Xbox" MinVersion="10.0.0.0" MaxVersionTested="10.0.0.0" />
  </Dependencies>


  • Iot
 <Dependencies>
    <TargetDeviceFamily Name="Windows.Iot" MinVersion="10.0.0.0" MaxVersionTested="10.0.0.0" />
  </Dependencies>



Good luck,

Msdn reference: https://msdn.microsoft.com/en-us/library/windows/apps/dn986903.aspx

dimanche 24 janvier 2016

Drag and Drop elements instead of using a FilePicker on Windows 10

Picking files with a FilePicker is no fun, why not let our users be able to drag and drop files in your application?


In this example I will show you who to implement a very simple drag and drop feature so that your users can just select a file they what to add to your app and just drag and drop it into your application.

First lest start by creating a Stackpanel and then we can start looking in the properties called Drop DragOver and AllowDrop:


Information taken from my IDE (Visual Studio):
We can see that Drop has the following information:

public event Windows.UI.Xaml.DragEventHandler Drop
    Member of Windows.UI.Xaml.UIElement

Summary:
Occurs when the input system reports an underlying drop event with this element as the drop target.
---------------------------------------------------------------------------------------------------------------------

We can see that DragOver has the following information:

public event Windows.UI.Xaml.DragEventHandler DragOver
    Member of Windows.UI.Xaml.UIElement

Summary:
Occurs when the input system reports an underlying drag event with this element as the potential drop target.
---------------------------------------------------------------------------------------------------------------------
And that AllowDrop has the following information:

public bool AllowDrop { get; set; }
    Member of Windows.UI.Xaml.UIElement

Summary:
Gets or sets a value that determines whether this UIElement can be a drop target for purposes of drag-and-drop operations.

Returns:
true if this UIElement can be a drop target for purposes of drag-and-drop operations; otherwise, false. The default is false.
---------------------------------------------------------------------------------------------------------------------

Lets get coding


In you XAML page you are going to want to create a StackPanel with the properties we saw above and add a small piece of text so that your users can see where to drop the file.


<StackPanel  
 Drop="StackPanel_Drop" 
 DragOver="StackPanel_DragOver" 
 AllowDrop="True">           
 
 <TextBlock    
  Margin="44,24,44,0"
  FontSize="24"
  Text="Drag and Drop your File here" />
</StackPanel>


In your .cs file you just need to handle the events  StackPanel_Drop and StackPanel_DragOver. In the event StackPanel_Drop you will just need to handle the file that the user is dropping in it, thanks to e.DataView.GetStorageItemsAsync() you are able to fecth the file the user wants to share with you and then you convert the first element in the array into a StorageFile and you are good to go.

Here is the code:

private async void StackPanel_Drop(object sender, DragEventArgs e)
        {
            if (e.DataView.Contains(StandardDataFormats.StorageItems))
            {
                var items = await e.DataView.GetStorageItemsAsync();
                if (items.Any())
                {
                    var storeFile = items[0] as StorageFile;
                    //Do what ever you wish with the StoreFile
                    //You code goes here
                }
            }
        }

private void StackPanel_DragOver(object sender, DragEventArgs e)
        {
            e.AcceptedOperation = DataPackageOperation.Copy;
        }

From here you can now upload the file to your server, or do whatever you wish!

Bonus: Just to make sure that users dont send you the wrong kind of file, its always a good idea to check the file extension. Here is a tiny method that will allow you check for different extensions on you file:

 private bool CheckFileExtension(string fileExtension)
        {
            string[] AllowedExtensions = new[] {".abc", ".def", 
            ".air",
            ".klm",
            ".fre",
            ".aqs",
            ".ovf" };

            return !AllowedExtensions.Contains(fileExtension);
        }


Happy Coding!