Written by Irmak Tevfik on 20 - Sep - 2014

Creating Universal Apps (MVVM) with Repository to get data from Services using Entity Framework as ORM hosted in Microsoft Azure.

This article will concentrate on step by step approach on creating a simple universal app (MVVM) by getting the data using Web API on Microsoft Azure.
For this simple project, lets say we will get list of video Urls and titles from our database. WebAPI application will be handling all of the logic and data will be sent to the client in JSON format.
On our client side application, we will be having a repository pattern to get/post data to the server. So the design of the project will look like the diagram below: 


Step 1: Create Database on Microsoft Azure
First, lets login to https://manage.windowsazure.com (alternative new portal https://portal.azure.com) to start. 
On the left hand side, we will be having NEW button to choose what needs to be added. Lets select DATA SERVICES -> SQL DATABASE -> QUICK CREATE.
To create our database we need to select Subscription, ServerName and a name for our database to start. for this example lets call it VideoApp.



Once database is ready, its time to create -our simple table for the model. I believe having Videotitle and VideoURL as columns will be enough for our example. so the query will be 
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[VideoFeeds](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [VideoTitle] [varchar](300) NOT NULL,
    [VideoUrl] [varchar](300) NOT NULL,
 CONSTRAINT [PK_VideoFeeds] PRIMARY KEY CLUSTERED
(
    [Id] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF)
)

to run this query lets click "Run Transact-SQL queries against your SQL database" from our newly created database dashboard which will bring us the Management portal.



simply lets run the query.

with this step we are done with Creating the database. Please we will be needing the Connection Strings for the SQL database, which can be gathered from the link "View SQL Database connection strings for ADO .Net, ODBC, PHP, and JDBC" in homepage.

Step 2: Creating the solution and the solution outlines
Lets jump to the Visual Studio to start working on the projects. If we analyse the project plan, we can conclude that  
1- Entity Framework and WebAPI projects will be running on the "Server Side" 
2- The "Repository (PCL)" and Universal app will be running on the "Client Side"

So lets create a new solution called VideoFeed with two folders named Client and Server as shown below.


Step 3: Creating Web API Controllers with Entity Framework
On this step, we will be using EF as our ORM. All of the CRUD operations will be handled over this project and it will be used in our controllers.
So lets begin with adding a class library and call it VideoFeedDAL (we can remove the default class called Class1.cs). 



this library will be holding our Db Model. So lets add a new Item "ADO.NET Entity Data Model" to our Library and call it "VideoFeedModel". 
Adding the item will prompt us with the steps to generate the Database Model. We will follow
1- Select "EF Designer From Database" option and go to the next step
2- We will be needing to create a new Connection to the Azure database from this point to generate the model so we will be needing the connection string that we copied from end of Step1. 

ServerName will be "Server=tcp:" and by using sql server authentication, user name is "User ID" and Password is the given password for the database to authenticate. After successful authentication, all we need is to select database and confirm.
If all of the settings are valid we should be having a form as below.


3-On the next step, Select version 6.x and follow next step
4-on this step, please select the table you would like to add and uncheck option to pluralize (as VideFeeds is allready pluralized). to complete as below.


Completing all of the steps will generate the current database model from azure as shown on the screenshot below.


Ok lets move to create our http Services and follow the steps below:
1- On the "Server" folder, Add a new "ASP.NET Web Application" under "Web" and name it as "VideoFeedServices".



2- Accepting the information will prompt you for selecting the template for the project. Go ahead and select Empty WebAPI project as we would like to adopt the project from scratch.

3- Go ahead and under controllers, add an empty "Web API 2 Controller" named as "VideoController".

Lets add the method below and test our Service:
public class VideoController : ApiController
{
[HttpGet]
public List<string> Test()
{
List<string> testlist = new List<string>();
testlist.Add("this is a test");
return testlist;
}
}

if we run http://localhost:53022/api/video/test , service will be returning :
<string>this is a test</string>
</ArrayOfstring>
Thats cool. That means we can jump to the next phase to tell WebAPI to use JSON as the default format.
4-Simply, if we would like to force our project to use JSON, all we need to add the codes below to the application_start under global.asax.

protected void Application_Start()
{
    GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
    GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.PreserveReferencesHandling = PreserveReferencesHandling.Objects;
    GlobalConfiguration.Configuration.Formatters.Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter);
    GlobalConfiguration.Configure(WebApiConfig.Register);
}
after rebulding the service and run the service, we will be getting the data in JSON format.
["this is a test"]

5-Now, Lets bind our Service with our EF project. To approach this task, first lets add VideoFeedDAL to the references of our Service project.


Integrating EF to the Service Project:
1-Currently we have a reference to the VideoFeedDAL entities but we cannot use any of the core functionalities of EF. For example, if we try to declare a new instance of VideoFeedDAL.VideoAppEntities as
VideoFeedDAL.VideoAppEntities con = new VideoFeedDAL.VideoAppEntities();
An error message of:
System.Data.Entity.DbContext' is defined in an assembly that is not referenced. You must add a reference to assembly 'EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.
will be thrown.

That means current project (WebAPI), can use the references of VideFeedDAL library but does not understand EF core functionalities. So lets go ahead, right click to References (Manage NuGet Packages) and add Entity Framework NuGet to the project as shown below.


All of the issues should we resolved after we add the EF nuget.
2- Lets add another simple Method to start with functionality.
[HttpGet]
public List<VideoFeedDAL.VideoFeeds> TestEF()
{
    //DbContext is IDisposable
    using (VideoFeedDAL.VideoAppEntities con = new VideoFeedDAL.VideoAppEntities())
    {
        //if there isnt any data, add some dummy
        if(con.VideoFeeds.Count() == 0)
        {
            con.VideoFeeds.Add(new VideoFeedDAL.VideoFeeds()
            {
                VideoTitle = "Some EF Video From Youtube",
            });
            con.SaveChanges();
             
        }
        var data = con.VideoFeeds.ToList();
        return data;
    }
}

This method will simply check if there is any record in VideoFeeds and add a dummy record if none exists. Finally it returns the records as List. Please note that we create the instance of VideoFeedDAL.VideoAppEntities by means of using().
As the class is IDisposable, it will release the resources and after we have done with it.
Lets try to debug and navigate to URL: http://localhost:53022/api/video/testEF 
Opps. we have another exception:

ExceptionMessage":"Multiple actions were found that match the request"

That's because of our routing in the App_Start/WebApiConfig.cs. Simply, our application has a default routing for api/{controller}/{id} which fails for this 
example as we cannot navigate it to the specific actions. Lets change default routing to:

config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{action}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );

Which will solve our problem. So lets move on and debug our project and navigate to  http://localhost:53022/api/video/testEF 
yet again. Now we have a new ExceptionMessage:

ExceptionMessage":"No connection string named 'VideoAppEntities' could be found in the application config file.

That exeption was expected. currently we have our connection string saved on VideFeedDAL project for EF. Our services need to have the reference on 
WebAPI web.config to be able to know the connection point. So all we need to do is 
Copy
<connectionStrings>
  <add name="VideoAppEntities" connectionString=".............
</connectionStrings>

From VideFeedDAL->app.config and Paste it to VideFeedServices->Web.config file under Configuration section.
Lets rebuild and run our service again and navigate to http://localhost:53022/api/video/testEF 
Now, service should be successful and will return us the result in JSON format:

[{"$id":"1","Id":1,"VideoTitle":"Some EF Video From Youtube","VideoUrl":"https://www.youtube.com/watch?v=Z7713GBhi4k&list=PL6n9fhu94yhUPBSX-E2aJCnCR3-_6zBZx"}]

3-Right now our services are ready and we can write our methods to get/post data to the azure database.
Before moving to the Client Side projects, lets add another method to see how parameters work in WebAPI.
Go ahead and add:
[HttpGet]
public List<VideoFeedDAL.VideoFeeds> TestEFWithParameter(string title)
{
    //DbContext is IDisposable
    using (VideoFeedDAL.VideoAppEntities con = new VideoFeedDAL.VideoAppEntities())
    {
        //only data we have currently is the record with title ""Some EF Video From Youtube". lets search the titles with the parameter
        var data = con.VideoFeeds.Where(p=>p.VideoTitle.Contains(title)).ToList();
        return data;
    }
}

this method will take a parameter called title and searches the videoFeeds where any of them contains that title. return result will be a list again.
to test, we can simply run http://localhost:53022/api/video/TestEFWithParameter?title=EF which will return:

[{"$id":"1","Id":1,"VideoTitle":"Some EF Video From Youtube","VideoUrl":"https://www.youtube.com/watch?v=Z7713GBhi4k&list=PL6n9fhu94yhUPBSX-E2aJCnCR3-_6zBZx"}]

4-Final step is to host our services in could. Go ahead and add these methods to the controller to finalize before deploying the project to Azure.
[HttpGet]
public List<VideoFeedDAL.VideoFeeds> GetAllVideos()
{
    using (VideoFeedDAL.VideoAppEntities con = new VideoFeedDAL.VideoAppEntities())
    {
        return con.VideoFeeds.ToList();
    }
}
 
[HttpGet]
public List<VideoFeedDAL.VideoFeeds> GetVideosByTitleSearch(string searchParameter)
{
    using (VideoFeedDAL.VideoAppEntities con = new VideoFeedDAL.VideoAppEntities())
    {
        return con.VideoFeeds.Where(p => p.VideoTitle.ToLower().Contains(searchParameter.ToLower())).ToList();
    }
}
Now we can use the services to get all the data we need. Next and final step is to deploy the services to Azure. Lets right click to "VideoFeedServices" project and select "Deploy". you will be prompt to select the publish Target.


Select Azure and Sign-in to your azure account. After your authentication is successful, we need to create a "New" website.
while creating the site we need to fill in some details:
Site Name: Go ahead and pick a name. in this example I will be using "VideoFeeds", which will generate me the site as videofeeds.azurewebsites.net
Subscription: Whatever subscription you are using.
Region: the Region you like your service to run on
Database Server: Select "No database" as we have already created and configured our settings.


After successful deploy. we now can use  to get our data. Let's test http://videofeeds.azurewebsites.net/api/video/GetAllVideos
Please note that after creating our models, we need to update our services a little. Lets move on to PCL projects.

Step 4: Creating Models on Portable Class Library
Lets make it clear that, we can reference PLC on Server projects (Such as HTTPService/Class Libraries) 
but we cannot use normal class references on portable classes and Store Apps(not as of today but EF team plans to support PCL on EF7 release ref(http://blogs.msdn.com/b/adonet/archive/2014/05/19/ef7-new-platforms-new-data-stores.aspx))
Our next attempt should be to create a portable class library for the Project Models so we can use the model mapping on our services to pass the data to the client application. Lets begin with step by step explanation:
1- First of all we need to add a portable class library to our "Client" folder under solution and name it "VideoAppModels" as shown below.

If we go to the properties of the library, we can see and set the targets of the PLC shown as below. we need to work on this section later on, so better to keep it in mind.


2-Go ahead and create a Class ,call it the same name as our table model (VideoFeeds) and add the model class to it as
public partial class VideoFeeds
{
    public int Id { get; set; }
    public string VideoTitle { get; set; }
    public string VideoUrl { get; set; }
}

Please note that all of the properties are same as our TABLE model in EF to reduce confusion.

3- Ok, now we are done with our model class. We need to do a quick change in our WebWPI project to change return data types to reference 
our Model class. So lets go back to "VideoFeedServices" project and add "VideoAppModels" project to the references.
On our attempt, we will be having an exception complaining "Unable to add a reference to the project 'VideoAppModels'. The current project's target is not one of or compatible with the targets of Portable Library Project 'VideoAppModels'"



This takes us back to step 1 as we need to target .NET Framework 4.5.1 to project.
Once done, we should be able to reference the project successfully.

Now the changes should be as:
[HttpGet]
public List<VideoAppModels.VideoFeeds> GetAllVideos()
{
    using (VideoFeedDAL.VideoAppEntities con = new VideoFeedDAL.VideoAppEntities())
    {
        return con.VideoFeeds.Select(p => new VideoAppModels.VideoFeeds() { Id = p.Id, VideoTitle = p.VideoTitle, VideoUrl = p.VideoUrl }).ToList();
    }
}
 
[HttpGet]
public List<VideoAppModels.VideoFeeds> GetVideosByTitleSearch(string searchParameter)
{
    using (VideoFeedDAL.VideoAppEntities con = new VideoFeedDAL.VideoAppEntities())
    {
        return con.VideoFeeds.Where(p => p.VideoTitle.ToLower().Contains(searchParameter.ToLower())).Select(p => new VideoAppModels.VideoFeeds() { Id = p.Id, VideoTitle = p.VideoTitle, VideoUrl = p.VideoUrl }).ToList();
    }
}

So we will be returning the data as list of VideoAppModels. carry on and redeploy the project.
Now lets jump to our Universal App project.

Step 5: Creating Universal App project with Repository
Simply lets add our empty universal app under our Client section of the solution and name it as  shown below.


Now you can notice that we have a shared project to feed a Windows Store app and a windows store app. we now aim to keep all of our logic/assets inside our shared app.



Lets start step by step:
1-Lets move all of our assets under the Shared project and delete the ones under windows/phone projects. So we will only be having our xaml pages.

2-Now, we will be needing some folders added to the Shared project:
Business: we will be keeping the helpers and the Client side business logic in this folder
Common: We will be keeping neccessary TemplateSelectors or our ICommand logic etc.. 
Library: Will be used to keep our main page items.
Repository: We will keep our Repository pattern under this folder for Get/Post logic
ViewModels: Will be used to keep our ViewModels for MVVM pattern. So after adding these folders our project will look like shown below.


3- Ok, we now need to add VideoAppModels and JSON.NET NuGet to our project. Please note that, we need to reference it to both Windows and Windows phone project to use it under Shared branch.


4-Lets go ahead to create our Repository. We can begin with adding a BaseRepository to our project (Shared->Repository folder) to inherit all classes use for all GET/POST from base.

public class BaseRepository
{
    private HttpClient httpClient = new HttpClient();
    private string ControllerName;
    //Change this line if you want to reference to another URL for VideoApp.Services
    private const string BaseUri = "http://videofeeds.azurewebsites.net/api/"; //this needs to be changed to the URI of your Service URL
 
    public static string FullUrl(UriString parameters, string MethodName, string ControllerName)
    {
        List<string> returnParams = new List<string>();
        if (parameters != null)
        {
            foreach (KeyValuePair<string, string> param in parameters._Params)
            {
                returnParams.Add(String.Format("{0}={1}", param.Key, param.Value));
            }
            var data = "?" + String.Join("&", returnParams.ToArray());
            return BaseUri + ControllerName + "/" + MethodName + data;
        }
        else
            return BaseUri + ControllerName + "/" + MethodName;
 
    }
 
    public BaseRepository(string BaseAddress)
    {
        HttpClientHandler handle = new HttpClientHandler();
        httpClient = new HttpClient(handle);
        httpClient.BaseAddress = new Uri(BaseUri);
        httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        httpClient.DefaultRequestHeaders.TryAddWithoutValidation("User-Agent", "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.146 Safari/537.36");
    }
 
    #region GetAsync
    protected async Task<T> GetAsync<T>([CallerMemberName]string MethodName = null, string ControllerName = null)
    {
        return await GetAsync<T>(null, MethodName, ControllerName);
    }
 
    protected async Task<T> GetAsync<T>(UriString parameters, [CallerMemberName]string MethodName = null, string ControllerName = null)
    {
        var result = await this.httpClient.GetAsync(FullUrl(parameters, MethodName, ControllerName));
        if (result.IsSuccessStatusCode)
        {
            return Newtonsoft.Json.JsonConvert.DeserializeObject<T>(await result.Content.ReadAsStringAsync());
        }
        else
        {
            return default(T);
        }
    }
 
    protected async Task<HttpResponseMessage> GetAsync([CallerMemberName]string MethodName = null, string ControllerName = null)
    {
        return await GetAsync(null, MethodName, ControllerName);
 
    }
 
    protected async Task<HttpResponseMessage> GetAsync(UriString parameters, [CallerMemberName]string MethodName = null, string ControllerName = null)
    {
        var fullUrl = BaseUri + ControllerName + MethodName + parameters.ToString();
        var result = await this.httpClient.GetAsync(FullUrl(parameters, MethodName, ControllerName));
        return result;
 
    }
 
    #endregion
}
public class UriString
{
    public Dictionary<string, string> _Params = new Dictionary<string, string>();
 
    public void Add(string key, string value)
    {
        _Params.Add(key, value);
    }
}

OK. Thats the base class that we are going to inherit our repository classes from. Please note that you need to customise BaseUri for your url of the services.
UriString will hold the parameter names and the values on the URL and FullUrl method will join the parameters with values to form a full URL for our HttpClient.
For this article example, we will only be using get async so,  our method will return Task of T and will need parameters of UriString, MethodName and Controller.

5- Let's move on by creating a Repository class named as "VideoSearchRepository" for video search as below:
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
 
namespace VideoApp.Repository
{
    public class VideoSearchRepository : BaseRepository, IDisposable
    {
        public async Task<List<VideoAppModels.VideoFeeds>> GetVideosByTitleSearch(string searchParameter)
        {
            UriString parameters = new UriString();
            parameters.Add("searchParameter", searchParameter);
            var obj = await base.GetAsync<List<VideoAppModels.VideoFeeds>>(parameters, "GetVideosByTitleSearch", "Video");
            return obj;
        }
 
        public async Task<List<VideoAppModels.VideoFeeds>> GetAllVideos()
        {
            var obj = await base.GetAsync<List<VideoAppModels.VideoFeeds>>("GetAllVideos", "Video");
            return obj;
        }
 
        public void Dispose()
        {
            GC.SuppressFinalize(this);
        }
    }
}

Usage is really simple. as I mentioned, you can add all of the parameters to the call by using UriString class. All of our async get methods are on our base class so we can await by simply referencing to our BaseRepository.
BTW I am being lazy with IDisposable. It needs to be handled 
correctly.

6- Ok, now we can jump to our simple Business class and add a class named VideoManager under our Business folder as below:
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
 
namespace VideoApp.Business
{
    public class VideoManager
    {
        public static async Task<List<VideoAppModels.VideoFeeds>> GetAll()
        {
            using (Repository.VideoSearchRepository rep = new Repository.VideoSearchRepository())
            {
                var VideoList = await rep.GetAllVideos();
                return VideoList;
            }
        }
    }
}

So static method will return all of the video links. we can continue to add small logic operations using repository under this folder. Aim is to keep repository access away from ViewModels.
7- Later on we will be needing a helper class. It is better to add it now. Add a folder named Helpers under Business folder and add a class called Extensions as shown below.

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text;
 
namespace VideoApp.Business.Helpers
{
    public static class Extensions
    {
        public static ObservableCollection<T> ToObservableCollection<T>(this List<T> col)
        {
            return new ObservableCollection<T>(col);
        }
    }
}

Later on we need to carry out some conversion to ObservableCollection.
8-Ok it is time to move to our ViewModel. before we start, we will be needing our RelayCommand class (inherit from ICommand) implemented so lets add our class under Common folder as:
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Input;
 
namespace VideoApp.Common
{
    /// <summary>
    /// A command whose sole purpose is to relay its functionality
    /// to other objects by invoking delegates.
    /// The default return value for the CanExecute method is 'true'.
    /// <see cref="RaiseCanExecuteChanged"/> needs to be called whenever
    /// <see cref="CanExecute"/> is expected to return a different value.
    /// </summary>
    public class RelayCommand : ICommand
    {
        private readonly Action _execute;
        private readonly Func<bool> _canExecute;
 
        /// <summary>
        /// Raised when RaiseCanExecuteChanged is called.
        /// </summary>
        public event EventHandler CanExecuteChanged;
 
        /// <summary>
        /// Creates a new command that can always execute.
        /// </summary>
        /// <param name="execute">The execution logic.</param>
        public RelayCommand(Action execute)
            : this(execute, null)
        {
        }
 
        /// <summary>
        /// Creates a new command.
        /// </summary>
        /// <param name="execute">The execution logic.</param>
        /// <param name="canExecute">The execution status logic.</param>
        public RelayCommand(Action execute, Func<bool> canExecute)
        {
            if (execute == null)
                throw new ArgumentNullException("execute");
            _execute = execute;
            _canExecute = canExecute;
        }
 
        /// <summary>
        /// Determines whether this <see cref="RelayCommand"/> can execute in its current state.
        /// </summary>
        /// <param name="parameter">
        /// Data used by the command. If the command does not require data to be passed, this object can be set to null.
        /// </param>
        /// <returns>true if this command can be executed; otherwise, false.</returns>
        public bool CanExecute(object parameter)
        {
            return _canExecute == null ? true : _canExecute();
        }
 
        /// <summary>
        /// Executes the <see cref="RelayCommand"/> on the current command target.
        /// </summary>
        /// <param name="parameter">
        /// Data used by the command. If the command does not require data to be passed, this object can be set to null.
        /// </param>
        public void Execute(object parameter)
        {
            _execute();
        }
 
        /// <summary>
        /// Method used to raise the <see cref="CanExecuteChanged"/> event
        /// to indicate that the return value of the <see cref="CanExecute"/>
        /// method has changed.
        /// </summary>
        public void RaiseCanExecuteChanged()
        {
            var handler = CanExecuteChanged;
            if (handler != null)
            {
                handler(this, EventArgs.Empty);
            }
        }
    }
}

It is important to notice that ICommand implements two methods CanExecute and Execute. Canexecute decides whether the command is enabled or disable depending on the condition and Execute mainly executes it.
9- Now we need to add the class to handle the model of the homepage items. we need to show a title for the group of items. so lets create our model class under "Library" folder as 
using System;
using System.Collections.Generic;
using System.Text;
 
namespace VideoApp.Library
{
    public class PageItems
    {
        public string Title { get; set; }
        public object Items { get; set; }
 
        public static List<PageItems> GetHomeData(List<VideoAppModels.VideoFeeds> obj)
        {
            List<PageItems> menu = new List<PageItems>();
            menu.Add(new PageItems()
            {
                Title = "Videos",
                Items = obj
            }
            );
            return menu;
        }
    }
}

As we can see, we will be setting the Title as Videos and pass our list to be displayed under that title.

10- OK. now lets create our ViewModel. Simply we will be needing :
 An ObservableCollection of our VideoModel
 A RelayCommand for searching the videos 

 Our UI will be having a Button to trigger RelayCommand to get all of the videos and populate our ObservableCollection. So lets add our ViewModel now (call it "HomePageViewModel").

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Text;
using System.Threading.Tasks;
using VideoApp.Common;
using VideoAppModels;
using VideoApp.Business.Helpers;
 
namespace VideoApp.ViewModels
{
    public class HomePageViewModel : INotifyPropertyChanged
    {
        #region change handling
        public event PropertyChangedEventHandler PropertyChanged;
        public void OnPropertyChanged(string propertyName)
        {
            //Fire the PropertyChanged event in case somebody subscribed to it
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
        #endregion
 
        private ObservableCollection<VideoFeeds> _videoFeed;
        public ObservableCollection<VideoFeeds> VideoFeed
        {
            get
            {
                return this._videoFeed;
            }
        }
 
        private RelayCommand _searchVideos;
 
        public HomePageViewModel()
        {
            _videoFeed = new ObservableCollection<VideoFeeds>();
            GetData();
        }
 
        private async Task GetData()
        {
            var data = await Business.VideoManager.GetAll();
            if (data != null)
                _videoFeed = data.ToObservableCollection();
        }
 
        #region Commands
        public RelayCommand SearchVideos
        {
            get
            {
                if (_searchVideos == null)
                {
                    _searchVideos = new RelayCommand(() => this.Search(), () => this.CanSearch());
                }
                return _searchVideos;
            }
            set
            {
                _searchVideos = value;
            }
        }
        #endregion
 
        private bool CanSearch()
        {
            //any logic  to prevent Searching
            return true;
        }
 
        private async void Search()
        {
            var data = await Business.VideoManager.GetAll();
            if (data != null)
            {
                _videoFeed = data.ToObservableCollection();
                this.OnPropertyChanged("VideoFeed");
            }
        }
    }
}

11- Final Step is to set our Xaml pages. Currently we have plain Xaml design as:
Windows 8.1
<Page
    x:Class="VideoApp.MainPage"
    xmlns:local="using:VideoApp"
    mc:Ignorable="d"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
 
    <Grid>
 
    </Grid>
</Page>

First we need to set the page to know its ViewModel. So lets add xmlns:ViewModel ="using:VideoApp.ViewModels" to our page references and 
 set our page context as
<Page.DataContext>
    <ViewModel:HomePageViewModel></ViewModel:HomePageViewModel>
</Page.DataContext>

Next lets add our page header by adding the code below to our main grid. This will be defining row definitions and set the Page Title as Text="{StaticResource AppName}" 
<Grid.ChildrenTransitions>
    <TransitionCollection>
        <EntranceThemeTransition />
    </TransitionCollection>
</Grid.ChildrenTransitions>
<Grid.RowDefinitions>
    <RowDefinition Height="140" />
    <RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="120" />
        <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>
    <TextBlock x:Name="pageTitle"
               Text="{StaticResource AppName}"
               Style="{StaticResource HeaderTextBlockStyle}"
               Grid.Column="1"
               IsHitTestVisible="false"
               TextWrapping="NoWrap"
               VerticalAlignment="Bottom"
               Margin="0,0,30,40" />
    <Button x:Name="test"
            Command="{Binding SearchVideos}"
            HorizontalAlignment="Right"
            VerticalAlignment="Top"
            Width="498"
            Margin="0,65,30,0"
            Grid.Column="1"
            Height="51"></Button>
</Grid>
You can observe that Text="{StaticResource AppName}" will complain that it can not resolve. we will be holding these resources under App.xaml. So lets go ahead and add resources.
<Application
    x:Class="VideoApp.App"
    xmlns:local="using:VideoApp">
    <Application.Resources>
        <x:String x:Key="AppName">Video Search</x:String>
    </Application.Resources>
</Application>

Now our page will know AppName will reference as "Video Search". So it will assist code integrity. Please note that we have bound Command="{Binding SearchVideos}" to the button on right hand side. Once this button clicked it will be triggering SearchVideos RelayCommand on our viewmodel. which will first check CanExecute and if it is successful, it will be running Execute.
Lets move on and add our main gridview to our page where we will be having our datatemplates and bindings.
<GridView x:Name="itemGridView"
             AutomationProperties.AutomationId="ItemGridView"
             AutomationProperties.Name="Grouped Items"
             Grid.RowSpan="2"
             Padding="116,137,40,46"
             SelectionMode="None"
             IsSwipeEnabled="false"
             IsItemClickEnabled="True"
             ItemsSource="{Binding VideoFeed}">
       <GridView.ItemTemplate>
           <DataTemplate>
               <Grid HorizontalAlignment="Left"
                     Width="250"
                     Height="66">
                   <StackPanel VerticalAlignment="Bottom"
                               Background="{ThemeResource ListViewItemOverlayBackgroundThemeBrush}">
                       <TextBlock Text="{Binding VideoTitle}"
                                  Foreground="{ThemeResource ListViewItemOverlayForegroundThemeBrush}"
                                  Style="{StaticResource TitleTextBlockStyle}"
                                  Height="60"
                                  Margin="15,0,15,0" />
                   </StackPanel>
               </Grid>
           </DataTemplate>
       </GridView.ItemTemplate>
       <GridView.ItemsPanel>
           <ItemsPanelTemplate>
               <ItemsWrapGrid GroupPadding="0,0,70,0" />
           </ItemsPanelTemplate>
       </GridView.ItemsPanel>
   </GridView>
As you can see we have ItemsSource="{Binding VideoFeed}" which is our ObservableCollection on our ViewModel and Text="{Binding VideoTitle}" will bind the VideoTitle to the DataTemplate.
So overall page xaml will look like:
<Page
    x:Class="VideoApp.MainPage"
    xmlns:local="using:VideoApp"
      xmlns:ViewModel="using:VideoApp.ViewModels"
      mc:Ignorable="d">
    <Page.DataContext>
        <ViewModel:HomePageViewModel></ViewModel:HomePageViewModel>
    </Page.DataContext>
    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <Grid.ChildrenTransitions>
            <TransitionCollection>
                <EntranceThemeTransition />
            </TransitionCollection>
        </Grid.ChildrenTransitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="140" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <GridView x:Name="itemGridView"
                  AutomationProperties.AutomationId="ItemGridView"
                  AutomationProperties.Name="Grouped Items"
                  Grid.RowSpan="2"
                  Padding="116,137,40,46"
                  SelectionMode="None"
                  IsSwipeEnabled="false"
                  IsItemClickEnabled="True"
                  ItemsSource="{Binding VideoFeed}">
            <GridView.ItemTemplate>
                <DataTemplate>
                    <Grid HorizontalAlignment="Left"
                          Width="250"
                          Height="66">
                        <StackPanel VerticalAlignment="Bottom"
                                    Background="{ThemeResource ListViewItemOverlayBackgroundThemeBrush}">
                            <TextBlock Text="{Binding VideoTitle}"
                                       Foreground="{ThemeResource ListViewItemOverlayForegroundThemeBrush}"
                                       Style="{StaticResource TitleTextBlockStyle}"
                                       Height="60"
                                       Margin="15,0,15,0" />
                        </StackPanel>
                    </Grid>
                </DataTemplate>
            </GridView.ItemTemplate>
            <GridView.ItemsPanel>
                <ItemsPanelTemplate>
                    <ItemsWrapGrid GroupPadding="0,0,70,0" />
                </ItemsPanelTemplate>
            </GridView.ItemsPanel>
        </GridView>
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="120" />
                <ColumnDefinition Width="*" />
            </Grid.ColumnDefinitions>
            <TextBlock x:Name="pageTitle"
                       Text="{StaticResource AppName}"
                       Style="{StaticResource HeaderTextBlockStyle}"
                       Grid.Column="1"
                       IsHitTestVisible="false"
                       TextWrapping="NoWrap"
                       VerticalAlignment="Bottom"
                       Margin="0,0,30,40" />
            <Button x:Name="test"
                    Command="{Binding SearchVideos}"
                    HorizontalAlignment="Right"
                    VerticalAlignment="Top"
                    Width="498"
                    Margin="0,65,30,0"
                    Grid.Column="1"
                    Height="51"></Button>
        </Grid>
    </Grid>
</Page>

And once we run and click to the button, we will be having the data as:


Lets go ahead and apply the xaml below to the Windows phone.
<Page
    x:Class="VideoApp.MainPage"
    xmlns:local="using:VideoApp"
    mc:Ignorable="d"
      xmlns:ViewModel="using:VideoApp.ViewModels"
      Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <Page.DataContext>
        <ViewModel:HomePageViewModel></ViewModel:HomePageViewModel>
    </Page.DataContext>
    <Grid>
        <ListView ItemsSource="{Binding VideoFeed}"
                  IsItemClickEnabled="True"
                  ContinuumNavigationTransitionInfo.ExitElementContainer="True"
                  Foreground="#FF191919">
            <ListView.Header>
                <Button Command="{Binding SearchVideos}"
                        Width="253">
 
                </Button>
            </ListView.Header>
            <ListView.ItemTemplate>
                <DataTemplate>
                    <Border CornerRadius="2"
                            BorderThickness="1"
                            Padding="0,5">
                        <StackPanel VerticalAlignment="Top">
                            <Grid HorizontalAlignment="Left"
                                  Width="250"
                                  Height="66">
                                <StackPanel VerticalAlignment="Bottom"
                                            Background="{ThemeResource ListViewItemOverlayBackgroundThemeBrush}">
                                    <TextBlock Text="{Binding VideoTitle}"
                                               Foreground="{ThemeResource ListViewItemOverlayForegroundThemeBrush}"
                                               Style="{StaticResource TitleTextBlockStyle}"
                                               Height="60"
                                               Margin="15,0,15,0" />
                                </StackPanel>
                            </Grid>
                        </StackPanel>
                    </Border>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </Grid>
</Page>

And once we run, we will be getting the result as follows:


Finally you can download the project from GitHub link below. But please remember that, you need to set your credentials (sql authentication, service login etc...) in config files to get it working.
Also please remember to change the baseAddress on Repository. 
https://github.com/irmaktevfik/VideoFeed

Enjoy coding :)

comments powered by Disqus