lundi 21 décembre 2015

Creating an expandable TextBlock control for WinRT, click to expand text

In this example we will look at how to create an expandable text block for a Windows 10 application.  I want a control on which I tell it its default height before it is expended and of course the text that need to be shown, a control that has a XAML code that looks like this:

 <controls:ExpandableTextBlock 
                Margin="0,0,0,0"
                CollapsedHeight="30"
                Text="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis lobortis libero vel justo sollicitudin auctor. Nulla blandit pulvinar augue ac feugiat. sit amet dolor. Suspendisse mattis dolor eu nulla volutpat, vitae accumsan sapien commodo.Vivamus id turpis sem."
            
                />

And that looks like this when its collapsed:


And like this when it is expended:



Let get coding:

First we will need to create a UserControl named ExpandableTextBlock, this control will contain one grid that holds 2 text blocks on that will hold our text and the other one that will hold our button or text that tells the user to click if he wishes to see the text.

Here is the XAML code:


 <Grid x:Name="LayoutRoot" Tapped="LayoutRoot_OnTap">
     <Grid.RowDefinitions>
          <RowDefinition Height="Auto" />
          <RowDefinition Height="Auto" />
      </Grid.RowDefinitions>

      <TextBlock  Grid.Row="0" 
                  x:Name="CommentTextBlock"  
                  HorizontalAlignment="Left" 
                  TextWrapping="Wrap"  
                  Height="Auto" 
                  Width="280"/>

      <StackPanel Grid.Row="1" 
                  Orientation="Horizontal" 
                  HorizontalAlignment="Right"
                  x:Name="ExpandHint" 
                  Visibility="Collapsed" 
                  Margin="0,5,0,0">
          <TextBlock  Text="View More" />
           <TextBlock Margin="10,0,10,0"
        Text="+" />
      </StackPanel>
</Grid>

We will need to create two DependencyProperty called Text and  CollapsedHeight which will allow you to pass the Text and the Height of your textblock to the UserControl.


        public static readonly DependencyProperty TextProperty = DependencyProperty.Register(
            "Text", typeof(string), typeof(ExpandableTextBlock), new PropertyMetadata(default(string), OnTextChanged));

        public string Text
        {
            get { return (string)GetValue(TextProperty); }
            set { SetValue(TextProperty, value); }
        }
       
        private static void OnTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var ctl = (ExpandableTextBlock)d;
            ctl.CommentTextBlock.SetValue(TextBlock.TextProperty, (string)e.NewValue);
            ctl.CommentTextBlock.SetValue(TextBlock.HeightProperty, Double.NaN);

            ctl.CommentTextBlock.Measure(new Size(ctl.CommentTextBlock.Width, double.MaxValue));

            double desiredheight = ctl.CommentTextBlock.DesiredSize.Height;
            ctl.CommentTextBlock.SetValue(TextBlock.HeightProperty, (double)63);

            if (desiredheight > (double)ctl.CommentTextBlock.GetValue(TextBlock.HeightProperty))
            {
                ctl.ExpandHint.SetValue(StackPanel.VisibilityProperty, Visibility.Visible);
                ctl.MaxHeight = desiredheight;
            }
            else
            {
                ctl.ExpandHint.SetValue(StackPanel.VisibilityProperty, Visibility.Collapsed);
            }

            //Setting length (width) of TextBlock
            var boundsWidth = Window.Current.Bounds.Width;
            ctl.CommentTextBlock.SetValue(TextBlock.WidthProperty, boundsWidth);
        }

        public static readonly DependencyProperty CollapsedHeightProperty = DependencyProperty.Register(
            "CollapsedHeight", typeof(double), typeof(ExpandableTextBlock), new PropertyMetadata(default(double), OnCollapsedHeightChanged));


        public double CollapsedHeight
        {
            get { return (double)GetValue(CollapsedHeightProperty); }
            set { SetValue(CollapsedHeightProperty, value); }
        }

        private static void OnCollapsedHeightChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var ctl = (ExpandableTextBlock)d;
            ctl.CollapsedHeight = (double)e.NewValue;
        }

in the OnTextChanged method you can see that we check to see if we need to show the hint that there is more text or not, as you can imagine it is pointless to show to the user an element saying that there is more text is there is not really more text.

and lastly we now need to create the méthode linked to the LayoutRoot_OnTap event, this methode will have to check to see if the content is fully visible or not and if not then show the whole content.


       private void LayoutRoot_OnTap(object sender, TappedRoutedEventArgs tappedRoutedEventArgs)
        {
           if ((Visibility)this.ExpandHint.GetValue(StackPanel.VisibilityProperty) == Visibility.Visible)
            {
                //transition
                this.CommentTextBlock.SetValue(TextBlock.HeightProperty, Double.NaN);

                this.ExpandHint.SetValue(StackPanel.VisibilityProperty, Visibility.Collapsed);
            }
        }

And there you have it, when the user clicks on the text block it will show the reste of the text.

Possible improvements:

You could add a third DependencyProperty that would allow you to manage the width of your text block thus instead of having the textblock taking the whole width of the screen like this:

//Setting length (width) of TextBlock
var boundsWidth = Window.Current.Bounds.Width;
ctl.CommentTextBlock.SetValue(TextBlock.WidthProperty, boundsWidth);

You could use a DependencyProperty to set the width.


Or you could also add another DependencyProperty which could manage the style of the TextBlock like this:



       public static readonly DependencyProperty TextStyleProperty = DependencyProperty.Register(
           "TextStyle", typeof(Style), typeof(ExpandableTextBlock), new PropertyMetadata(default(Style), OnTextStyleChanged));

        public Style TextStyle
        {
            get { return (Style)GetValue(TextStyleProperty); }
            set { SetValue(TextStyleProperty, value); }
        }

        private static void OnTextStyleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var ctl = (ExpandableTextBlock)d;
            ctl.CommentTextBlock.SetValue(StyleProperty, (Style)e.NewValue);
        }


Happy coding.

you can find the Github code here


mardi 15 décembre 2015

Using Live Visual Tree and Live Property Explorer to customize the Media Player (XAML, C#)

In this series of tutorials on how to customize your MediaPlayer, we have seen how to customize a button in part I. Now we will see how we can use Live Visual Tree and Live Property to make our lives easier when we are trying to design our MediaPlayer element. 
The rest my my article on the Dailymotion blog  here.

lundi 14 décembre 2015

Using the new .NET Facebook SDK in Windows 10 apps (UAP) C# and setting up you Facebook developer account

I was migrating one of my applications that was using the old Facebook SDK and that did not work at all in my new UAP application.  Search the web i found that Facebook had developed a new SDK for UAP apps.  Here is a small tutorial of what i had to do to make this SDK work with my current code.

What you need to have:
- FacebookId
- cloned FacebookSDK: https://github.com/Microsoft/winsdkfb
- Blank UAP app

I am using Visual Studio 2015 and a UAP application so I had to add this project to my application:
FBWinSDK\FBSDK-UWP\FBSDK-UWP\FBSDK-UWP.vcxproj
and then add the reference to my blank app.

your application should look as follows:



 Next we are going to need to get the Id of our application :

string SID = WebAuthenticationBroker.GetCurrentApplicationCallbackUri().ToString();

you will need to add this using of this code to work:

using Windows.Security.Authentication.Web;

Next we need to get the Facebook session, we will need our Facebook Id and our Windows Application id as follow:

FBSession sess = FBSession.ActiveSession;
sess.FBAppId = "<Facebook App ID>";
sess.WinAppId = "<Windows or Windows Phone Store ID depending on the target device>";

you will need to add this using of this code to work:

using Facebook;

And lastly we need to get the login prompt and set the permitions, the permitions are to be set in a list of strings:

// Add permissions required by the app 
        private static readonly List<string> PermissionList = new List<String>() { "user_about_me", "email", "publish_actions" };

And here is the login code:

 FBPermissions permissions = new FBPermissions(PermissionList);

        
                // Login to Facebook
                FBResult result = await sess.LoginAsync(permissions);

                if (result.Succeeded)
                {
                    // Login successful
                    return sess.AccessTokenData.AccessToken;
                }
                else
                {
                    // Login failed
                    return null;

                }

In the application that you can find on Github, you will fnd evrything on one page:


    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();
        }

        // Add permissions required by the app 
        private static readonly List<string> PermissionList = new List<String>() { "user_about_me", "email", "publish_actions" };



        public async Task<string> LogIntoFacebook()
        {
            //getting application Id
            string SID = WebAuthenticationBroker.GetCurrentApplicationCallbackUri().ToString();

            // Get active session
            FBSession sess = FBSession.ActiveSession;
            sess.FBAppId = Dailymotion.Core.Constants.FacebookAppId;
            sess.WinAppId = SID;

            //setting Permissions
            FBPermissions permissions = new FBPermissions(PermissionList);

            try
            {
                // Login to Facebook
                FBResult result = await sess.LoginAsync(permissions);

                if (result.Succeeded)
                {
                    // Login successful
                    return sess.AccessTokenData.AccessToken;
                }
                else
                {
                    // Login failed
                    return null;

                }
            }
            catch (InvalidOperationException ex)
            {
                //error handling
                return null;
            }
            catch (Exception ex)
            {
                //error handling
                return null;
            }
        }

        private async void ButtonBase_OnClick(object sender, RoutedEventArgs e)
        {
            //get the access token to login
            var result = await LogIntoFacebook();
        }
    }

Setting up your account


Next you will need to access you developer account on Facebook: https://developers.facebook.com/apps/

You will need to create a new app, you fill find you app Id here and then you will need to setup the Windows Store SID that you can find in your application and add it  here under the setting panel.



Update 1:
To make this work you also need to go to Facebook Developer website: https://developers.facebook.com
under: your app name -> Settings -> Advance:
And then under: Valid OAuth redirect URIs you need to add: https://www.facebook.com/connect/login_success.html
Save and you are good to go now! enter image description here


Github code: here

SDK; https://github.com/Microsoft/winsdkfb

More information here:
http://blogs.windows.com/buildingapps/2015/07/14/windows-sdk-for-facebook/

lundi 7 décembre 2015

Re-purposing Media Player Framework (3.0.0.1) buttons to do something else (XAML,C#)


In this small example I will explain why I re-purposed some media player buttons on my MediaPlayer.  At first I was looking into creating a whole new button and linking it with events using MVVM with a RelayCommand, I wanted to do this well of course.

To start I wanted to create my own button from scratch and bind it with an event, this quickly became difficult as I am not a great designer (looking at my apps you will quickly understand what I mean) and binding an event on events that are that deep (in a ControlTemplate) is not always the best idea or the easiest.  It does work and it is doable, however I was sometimes getting some issues on the tapped event which was not being fired (probably the tapped event was getting caught by some other button in the player).

So I started looking at my XAML code to see what I could do:

  <playerFramework:MediaPlayer
                x:Name="Player"
                Background="Transparent"
                IsPlayPauseVisible="True"
                Opacity="1"       
                />       

The C# code for my player looked as follow:

                    Player.Source = MySource;
                    Player.MediaOpened += Player_OnMediaOpened;
                    Player.MediaClosed += Player_MediaClosed;
                    Player.Play();

and then it hit me! why dont I just re-use some of the buttons on the player that I am not using.  This would allow my to not have to re code all of the different events linked to the button and also have the effects already coded for me like the on press event and mouse over events and more.

 In my example I decided to re purpose the full screen button to start,  all we need to do on the MediaPlayer is to show the FullScreenButton:

  <playerFramework:MediaPlayer
                x:Name="Player"
                VerticalAlignment="Bottom"
                HorizontalAlignment="Left"
                Background="Transparent"
                IsFullScreenEnabled="True"    <- this
                IsFullScreenVisible="True"    <- this
                IsPlayPauseVisible="True"
                Opacity="1"       
                />       



Then we just need to catch the isFullScreenChanged event like this:

        
private void InitPlayer()
{
        Player.Source = MySource;
        Player.MediaOpened += Player_OnMediaOpened;
        Player.MediaClosed += Player_MediaClosed;
        Player.IsFullScreenChanged += Player_IsFullScreenChanged;
        Player.Play();
}



 private void Player_IsFullScreenChanged(object sender, RoutedPropertyChangedEventArgs<bool> e)
        {
            //do what ever you want to do...
        }


And now you can do whatever you wish when the full screen button is clicked on the player.

Next we will edit the AppBarButton style so that we show our custom button, like I have written in previous articles you need to get the default style of the AppBarButton and edit it as you need. For this example we will just edit the element <Viewbox> comment its Ellipse and ContentPresenter and add an image:

    <Style x:Key="PlayerAppBarCloseButtonStyle" TargetType="AppBarButton">
        <!--<Setter Property="Foreground" Value="{ThemeResource AppBarItemForegroundThemeBrush}"/>-->
        <Setter Property="Foreground" Value="Black" />
        <Setter Property="VerticalAlignment" Value="Center" />
        <Setter Property="HorizontalAlignment" Value="Center" />
        <Setter Property="Padding" Value="0" />
        <Setter Property="IsCompact" Value="True" />
        <Setter Property="Height" Value="40" />
        <Setter Property="Width" Value="40" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="AppBarButton">
                    <Grid x:Name="RootGrid" Background="Transparent">
                        <VisualStateManager.VisualStateGroups>
                            <VisualStateGroup x:Name="ApplicationViewStates">
                                <VisualState x:Name="FullSize" />
                                <VisualState x:Name="Compact" />
                            </VisualStateGroup>
                            <VisualStateGroup x:Name="CommonStates">
                                <VisualState x:Name="Normal" />
                                <VisualState x:Name="PointerOver" />
                                <VisualState x:Name="Pressed" />
                                <VisualState x:Name="Disabled" />
                            </VisualStateGroup>
                            <VisualStateGroup x:Name="FocusStates">
                                <VisualState x:Name="Focused" />
                                <VisualState x:Name="Unfocused" />
                                <VisualState x:Name="PointerFocused" />
                            </VisualStateGroup>
                        </VisualStateManager.VisualStateGroups>
                        <Viewbox Margin="{TemplateBinding Padding}">
                            <Grid Width="45" Height="45">
                                <Ellipse x:Name="BackgroundEllipse"
                                         Width="45"
                                         Height="45"
                                         Fill="#BBFFFFFF"
                                         UseLayoutRounding="False" />

                                <!--<Ellipse x:Name="BackgroundEllipse" Fill="{ThemeResource AppBarItemBackgroundThemeBrush}" UseLayoutRounding="False"/>-->
                                <!--<Ellipse x:Name="OutlineEllipse" Stroke="{ThemeResource AppBarItemForegroundThemeBrush}" StrokeThickness="2" UseLayoutRounding="False"/>-->
                                <!--<ContentPresenter x:Name="Content" AutomationProperties.AccessibilityView="Raw" Content="{TemplateBinding Icon}" Foreground="Black" HorizontalAlignment="Center" VerticalAlignment="Center"
                                                  Height="45"
                                                  Width="45"
                                  Opacity="1"
                                                  />-->
                                <Image Width="25"
                                       Height="25"
                                       Margin="10"
                                       Source="/Assets/VideoPage/close.png" />

                            </Grid>
                        </Viewbox>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

Lastly we just need to link this style to our FullScreenButton which should be located in your ControlTemplate of the video media element as follow:


 <AppBarButton x:Name="FullScreenButton"
               Width="45"
               Height="45"
               Margin="8,0,8,0"
               Style="{StaticResource PlayerAppBarCloseButtonStyle}"               Visibility="{Binding IsFullScreenButtonVisible,
                            Converter={StaticResource VisibleIfConverter},
                              RelativeSource={RelativeSource Mode=TemplatedParent}}">
                      <local:MediaControls.Behavior>
                          <local:FullScreenButtonBehavior ViewModel="{Binding ViewModel, RelativeSource={RelativeSource Mode=TemplatedParent}}" />
                      </local:MediaControls.Behavior>
 </AppBarButton>

And there you have it, you have re purposed an AppBarButton to do what you need it to do.  I used the FullScreenButton but you could have used any other button that you are not using as long as it has a Changed event linked to it!

Happy coding.

As a great philosopher once said "Rien ne se perd, rien ne se crée, tout se transforme."  Antoine Lavoisier

lundi 30 novembre 2015

Proof of Concept: Trying to update PubCenter Ad ID and Ad Unit Id without having to resubmit your application

Proof of Concept: What if I wanted to create my own Ad manager that would allow me to be able to change the PubCenter Ad Id and Unit Id without having to resubmit the app.

 Here is the main idea behind this POC:
  • The different steps, first we will create a json file that will hold our default information.
  • Next when the application first launch’s it will read this file and store the information to memory.
  • Afterward we will call an endpoint with an updated version of the XML file and will copy the information of this json into that one if and only if the updated version has a higher version number.
  • Next when the UserControl containing the PubCenter ( or something else) ad is called it will read in memory the different values and pass them to the PubCenter element.
Lets get Coding!!

But first you need some place to store the file that will hold your information, you can either use your own server or dropbox, because I wanted to go quickly for this POC I used dropbox: https://www.dropbox.com/s/ruoe5dknprvn68d/ExampleAds.txt?dl=1

Now we can really start coding

  • You will need to create a file called DefaultAds.txt at the root of your app files, with the following content:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
{
  "AdSettings": {
    "Created" : "05102015",
    "Version" : "1",
    "AdElement": [
      {
        "Type": "small",
        "Kind": "Image",
        "AppID": "fb7f2816-4607-4508-86ee-e5c2058b627e",
        "AdID": "220045"
      },
      {
        "Type": "small",
        "Kind": "Image",
        "AppID": "fb7f2816-4607-4508-86ee-e5c2058b627e",
        "AdID": "220048"
      },
      {
        "Type": "medium",
        "Kind": "Post",
       "AppID": "fb7f2816-4607-4508-86ee-e5c2058b627e",
        "AdID": "220046"
      },
      {
        "Type": "medium",
        "Kind": "Post",
        "AppID": "fb7f2816-4607-4508-86ee-e5c2058b627e",
        "AdID": "220047"
      },
      {
        "Type": "medium",
        "Kind": "Main",
          "AppID": "fb7f2816-4607-4508-86ee-e5c2058b627e",
        "AdID": "220049"
      }
    ]
  }
}
  • Then we are going to create a class named AdPubcenterService in which we will add a method called ReadFileFromStorageFile which will luck as follows:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
private async static Task ReadFileFromStorageFile()
        {
            var adSettings = new AdSettingsRoot();

            try
            {
                String ResourceReference = "ms-appx:///DefaultAds.txt";
                StorageFile file = await StorageFile.GetFileFromApplicationUriAsync(new Uri(ResourceReference, UriKind.Absolute));
                Stream src = await file.OpenStreamForReadAsync();

                using (StreamReader sr = new StreamReader(src))
                {
                    string text = sr.ReadToEnd();
                    adSettings = JsonConvert.DeserializeObject<AdSettingsRoot>(text);
                }

                //Updating data
                App.AdSettingsBase.AdElement_Small1 = adSettings.AdSettings.AdElement[0];
                App.AdSettingsBase.AdElement_Small2 = adSettings.AdSettings.AdElement[1];
                App.AdSettingsBase.AdElement_Medium_1 = adSettings.AdSettings.AdElement[2];
                App.AdSettingsBase.AdElement_Medium_2 = adSettings.AdSettings.AdElement[3];
                App.AdSettingsBase.AdElement_Medium_Main = adSettings.AdSettings.AdElement[4];

                App.AdSettingsBase.Version = adSettings.AdSettings.Version;
                App.AdSettingsBase.LastUpdated = Convert.ToDateTime(adSettings.AdSettings.Created);
            }
            catch (Exception e)
            {
                //Catch errors here
            }
        }


  • Now that we can read our file localy we also need to be able to ready our file that is store somewhere on on the web (on dropbox for me).  I will create a method call GetAdsFromHttpJsonFiles which will read our local file first, then make a call to our url and save the data for the url.



 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
        public static string PageUrl = "https://www.dropbox.com/s/ruoe5dknprvn68d/ExampleAds.txt?dl=1";

        public static async Task GetAdsFromHttpJsonFiles()
        {
            await ReadFileFromStorageFile();

            AdSettingsRoot adSettings = new AdSettingsRoot();
            bool error = false;

            try
            {
                var req = new HttpClient();
                var message = new HttpRequestMessage(HttpMethod.Get, PageUrl);

                var response = await req.SendAsync(message);
                string result = await response.Content.ReadAsStringAsync();
                adSettings = JsonConvert.DeserializeObject<AdSettingsRoot>(result);
            }
            catch (Exception e)
            {
                error = true;
            }

            ParseElementForAds(adSettings);
        }



  • The Method ParseElementForAds is what allow us to save information that we have store outside our application.  In this method:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
     private static void ParseElementForAds(AdSettingsRoot elementRoot)
        {
            bool updateFile = false;

            //Makign sure the file is not empty
            if (elementRoot.AdSettings != null)
            {
                //if Initialsing file is needed
                if (App.AdSettingsBase == null)
                {
                    App.AdSettingsBase = new AdSettingsBase();
                    updateFile = true;
                }

                //Checking the version
                int version = (int)(elementRoot.AdSettings.Version);

                //if new gotten elements are newer then the one i have update the settings file
                if (!updateFile && App.AdSettingsBase.Version < version)
                {
                    updateFile = true;
                }

                //making sure that we should update the file & that we have the correct count
                if (updateFile && elementRoot.AdSettings.AdElement.Count == 5)
                {
                    App.AdSettingsBase.Version = version;
                    App.AdSettingsBase.LastUpdated = DateTime.Now;

                    App.AdSettingsBase.AdElement_Small1 = elementRoot.AdSettings.AdElement[0];
                    App.AdSettingsBase.AdElement_Small2 = elementRoot.AdSettings.AdElement[1];
                    App.AdSettingsBase.AdElement_Medium_1 = elementRoot.AdSettings.AdElement[2];
                    App.AdSettingsBase.AdElement_Medium_2 = elementRoot.AdSettings.AdElement[3];
                    App.AdSettingsBase.AdElement_Medium_Main = elementRoot.AdSettings.AdElement[4];

#pragma warning disable 4014
                    SaveFileFromStorageFile(elementRoot);
#pragma warning restore 4014

                }
            }
        }
   
  • Next we will create a UserControl and add pubcenter XAML to it:
1
2
3
4
5
6
 
<ui:AdControl x:Name="AdMain"
                  Width="490"
                  Height="80"
                  Margin="0,0,0,0"
                  HorizontalAlignment="Left"
                  ErrorOccurred="AdControl_OnErrorOccurred" />

  • And when the user control is initialized we will pass our AdI d and AppId to the PubCenter Controller:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
  public PublicityUserControl()
        {
            this.InitializeComponent();

            try
            {
                if (App.AdSettingsBase != null)
                {
                    AdMain.AdUnitId = App.AdSettingsBase.AdElement_Medium_1.AdID; //"219859";
                    AdMain.ApplicationId = App.AdSettingsBase.AdElement_Medium_1.AppID; //"45e36de2-ed28-4ca7-9eea-779875b65700"; 
                }
            }
            catch (Exception e)
            {
              
            }
        }

        private void AdControl_OnErrorOccurred(object sender, AdErrorEventArgs e)
        {
            Debug.WriteLine(e.Error);
        }

And there you have it, you can now manage you Ad Id and App Id from a remote location without having to resubmit your application every time!

Here is the source code: https://onedrive.live.com/redir?resid=70A41C6835F56338!39329&authkey=!ANWpJkTH9Bpn5ho&ithint=file%2czip


lundi 23 novembre 2015

Why using Template 10 is a great idea in a Universal Application

Template10 is on Github

When you first install Visual Studio 2015 and want to start developing for windows 10 all you get an empty blank template...  which is not great.



At least in when we started developing for Windows 8.1 we had the option to start with different tempaltes:
  • Blank App
  • Hub App
  • Grid App
  • And more
As you can see here:



So why when we want to create a Windows Universal App in Visual Studio 2015 we only have a blank application template where is the love!!

Why did the Visual Studio Team do this to us?  did we do something wrong? I don't know... but I found a solution and this is where Jerry Nixon and the Github community comes in and try to give you a hand!

Template 10: https://github.com/Windows-XAML/Template10 is a Windows app project template that can help you speed up your development time!

Thanks to the great job of the community Template 10 allows us Universal application developers for Windows 10 to have a very nice starting base for your development and it also gives you conventions that you SHOULD follow =).

Here are the conventions that Template 10 uses:
  1. Views (XAML files) are located in an /Views folder (and ns)
  2. Only have one view-model for one view
  3. View-models are located in a /ViewModels folder (and ns)
  4. Use OnNavigatedTo in view-models, not pages
  5. Models are located in a /Models folder (and ns)
  6. Use the façade pattern with our models
  7. Navigate using a NavigationService
  8. Communicate with a Messenger
  9. Dependency Injection
  10. We use Template 10 ;-)
Help us make Template 10 more robust and help the Github community  by asking questions and contributing if you can!  I have recently done a pull request so that if you (like me) are migrating your existing application from a Windows Phone or Windows Store application that was using Mvvm Light, you can keep on using your current properties without having to add Mvvm Light to your project.   Because yes Template 10 does ship with a mini Mvvm Framework, that being said you should use your favorite Mvvm Framework.

I'll let you check out the Github repository: https://github.com/Windows-XAML/Template10
Or you can download the Visual Studio template here: https://visualstudiogallery.msdn.microsoft.com/60bb885a-44e9-4cbf-a380-270803b3f6e5



Thanks for reading.

lundi 9 novembre 2015

Customizing your Media Player Framework on Windows Phone (XAML, C#)

I have written and article on how to customize your Media Player Framework on my company engineering blog.

As you know here at Dailymotion we strive to deliver the best video player experience no matter what platform you are on (Windows, iOS, Android etc).

Thus, I have spent a lot of time customizing the Media Player for our Windows apps and needless to say that it has been a long journey for me because of the lack of any good tutorials and examples. Many times I used trial and error to try and figure out what worked and what did not.

You can find the rest of the article here

mercredi 4 novembre 2015

Detecting if an object is outside of the screen for Windows (8/8.1) Store Apps (C#/XAML)

How to detect if an object is intersecting with another object
This is a tutorial on how to implement a methode that allows us to see if you have 2 objects that are intersecting with one another. I mainly use this to see if an object is outside of the screen for the user and thus need to show him something else when that object is not visible anymore.
If you don't want to have to look at the code here is the important part, these two methodes IsObjectHidden and IntersectsWith.

  IsObjectHidden Methode

//the object of this methode is to create 2 rectangles, from our two objects and see they intersect or not
protected bool IsObjectHidden(FrameworkElement child, FrameworkElement scrollViewer, int Offset)
{
    //Getting the information related to the scrollViewer
    GeneralTransform childTransform = child.TransformToVisual(scrollViewer);
    //creating out first rectangle using the object that i wish to ttrack
    Rect childRectangle = childTransform.TransformBounds(new Rect(new Point(0, 0), child.RenderSize));
    //creating out second rectangle  using the scrollViewer
    Rect ownerRectangle = new Rect(new Point(0, 0), scrollViewer.RenderSize);
    //Testing
    bool isInterset = IntersectsWith(childRectangle, ownerRectangle, Offset);
    return !isInterset;
}

  IsObjectHidden

//the object of this methode is to create 2 rectangles, from our two objects and see they intersect or not
public static bool IntersectsWith(Rect rect, Rect other, int offset)
{
    // Test for separating axis on the two rectangles
    if (other.Bottom < rect.Top || other.Right < rect.Left
    || other.Top > rect.Bottom || other.Left > (rect.Right - offset))
    {
        return false;
    }
    return true;
}
I have only tested this on Windows Store apps, happy coding.

mardi 27 octobre 2015

New Imgur .NET SDK on Github, can be used Universal App, WinRT app, Windows Phone, any .net project


Github Repo: https://github.com/Delaire/Imgur-.NET-SDK

How to use this sdk:

You first need to get your API key and secret id which you can find on the imgur website https://api.imgur.com/oauth2/addclient and/or here if you already have a done this: https://imgur.com/account/settings/apps
To start you need to initialize the api:
    ApiRoot.Instance.Init("XXXXXXXX", "XXXXXX");
All of the methods are async, so just remember that you need to wait for the response.
I have mapped all of the imgur api endpoint which can be found here: https://api.imgur.com/endpoints to classes.

Here is example of how the API works with the GetEndPointEntityAsync method:
You will tell the method the type of data you plan on receiving and then tell it where to get this data:
    ApiRoot.Instance.GetEndPointEntityAsync<RootElement<Data_Format_we_will_recieve>>(
                      new Data_to_get()
                          {
                                    //Data parameters
                          });
Here is a real example for how you can make a call:
    var result = await ApiRoot.Instance.GetEndPointEntityAsync<RootElement<GalleryImage>>(
            new GetGalleryImage ()
            {
                page = 0,
                section = Section.hot.ToString(), <- cloud be improved
                showViral = true,
                sort = Sort.top.ToString(),
                window = WindowsSort.day.ToString(),
            });
Here is another example of how to do a Get Random Gallery Image
    ApiRoot.Instance.GetEndPointEntityAsync<RootElement<GalleryAlbum>>(
                 new GetRandomGalleryImages()
                    {
                            page = 1
                    });

This API sdk is used in my personal windows phone imgur app 8gur which can be found here: http://windowsphone.com/s?appid=15913087-9ea1-4f42-92b0-8b2c1c764837
if you wish to help be my guest!
Here is the Github Repo: https://github.com/Delaire/Imgur-.NET-SDK


mercredi 21 octobre 2015

Using AppVeyor CI to build a Windows Phone 8.1 XAML App with Ad Mediator and Player Framework, what I had to do, to make it work!

What I want to do:
As a developer I am LAZY and like to make sure that when I push code to my GitHub repo that it doesn’t break everything, that is why I love AppVeyor. AppVeyor will build my app or code every time a push code to Github.

Lets get Started:
I have create a sample application called ‘’ExampleApp‘’ which contains the references that can’t just installed using nugget.

Usually on AppVeyor to load the libraries needed to build the application you would go into settings:


Then into Build:



And making sure that before the build is built you launch a script that will restore all of your nuget packages: nuget restore ExampleApp \ExampleApp.sln

Side note: make sure that you select platform version x86, ARM or else Ad Mediation will not build.

For our sample app that I want AppVeyor to build, I will add 2 references Ad Mediator and Microsoft player Framework before the application is built:

Here is a screenshot of the references of my app:


AppVeyor cannot load these references using nuget, so we are going to have to write a PowerShell script (please don’t start running this will be simple!! I Promise).

AppVeyor spawn a VM every time you launch a build of your project so running a PowerShell script should be easy! And its even easier thanks to their interface.

To Start:

You need to find the correct .msi & .vsix files needed to be installed on the machine.  Here are the Urls for the two files that I need to install:

  1. For Ad Mediation the url is ‘https://visualstudiogallery.msdn.microsoft.com/401703a0-263e-4949-8f0f-738305d6ef4b/file/146057/6/AdMediator.msi’ 

  2. For Player Framework 2.0 the Url is ‘http://download-codeplex.sec.s-msft.com/Download/Release?ProjectName=playerframework&DownloadId=845206&FileTime=130449531816430000&Build=21031’

Once you have found those urls we can use this PowerShell script:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
Write-Host "Installing Microsoft Universal Ad Client SDK..."
$msiPath = "$($env:USERPROFILE)\AdMediator.msi"
(New-Object Net.WebClient).DownloadFile('https://visualstudiogallery.msdn.microsoft.com/401703a0-263e-4949-8f0f-738305d6ef4b/file/146057/6/AdMediator.msi', $msiPath)
cmd /c start /wait msiexec /i $msiPath /quiet
Write-Host "Installed" -ForegroundColor green
 
 
Write-Host "Installing Microsoft Player Framework 2.0 ..."
$vsixPath = "$($env:USERPROFILE)\Microsoft.PlayerFramework.vsix"
(New-Object Net.WebClient).DownloadFile('http://download-codeplex.sec.s-msft.com/Download/Release?ProjectName=playerframework&DownloadId=845206&FileTime=130449531816430000&Build=21031', $vsixPath)
"`"C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\VSIXInstaller.exe`" /q /a $vsixPath" | out-file ".\install-vsix.cmd" -Encoding ASCII
& .\install-vsix.cmd
Write-Host "Installed" -ForegroundColor green


side note: remember that this script needs to run before the build is launched.


Launch your build and Eureka, the build passes:



I hoped this small tutorial has helped you out in better using AppVeyor.


Bonus 1
You can connect to the VM AppVeyor spawns to debug and see what packages you are missing using:

1
$blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))


In the console you will get the information you need (Server IP, Username, Password) to connect to the VM using a Remote Desktop:



Bonus 2
AppVeyor allow you to have a badge on your Github repo which allows you to know if the build is building or not =).  This can be found in MyProject -> Settings -> Badges, here is an example of my badge
https://ci.appveyor.com/api/projects/status/tie0te4no2uxlxn5?svg=true



 PS: this is my first post, so please don’t hesitate to writ e comment and tell me if you liked it or not!