tag:blogger.com,1999:blog-49953341640490028572024-02-07T21:06:19.582+01:00Christian Helle's Blog (Moved to christianhelle.com)This blog is moved to a new home - https://christianhelle.comChristian Resma Hellehttp://www.blogger.com/profile/16521776612083091477noreply@blogger.comBlogger98125tag:blogger.com,1999:blog-4995334164049002857.post-18686659064013355192022-09-07T18:27:00.003+02:002022-09-17T18:07:28.408+02:00This blog is moving to a new home - https://christianhelle.com<h1 style="text-align: left;">All future content will be posted on <a href="https://christianhelle.com">https://christianhelle.com</a> </h1><div>After being on Blogger since early 2007, I have decided to move on to hosting my blog on Github Pages using Jekyll and markdown instead of HTML</div><div><br /></div><div>I converted the entre history (excluding comments) to the new blog</div>Christian Resma Hellehttp://www.blogger.com/profile/16521776612083091477noreply@blogger.com0tag:blogger.com,1999:blog-4995334164049002857.post-61203549575405888162020-03-01T21:31:00.001+01:002020-03-01T21:32:22.348+01:00AppCenter Extensions for ASP.NET Core and Application InsightsIn my <a href="https://christian-helle.blogspot.com/2020/02/appcenter-extensions-for-xamarinforms.html">previous post</a>, I wrote about an open source project called <a href="https://github.com/christianhelle/appcenterextensions">AppCenterExtensions</a> available at Github and nuget.org. I recently updated this project and added a few components for ASP.NET Core that enables including AppCenter diagnostic information in Application Insights.<br />
<br />
The NuGet package is called <a href="https://www.nuget.org/packages/AppCenterExtensions.AppInsights">AppCenterExtensions.AppInsights</a> and contains extension methods and <a href="https://docs.microsoft.com/en-us/dotnet/api/microsoft.applicationinsights.extensibility.itelemetryinitializer">ITelemetryInitializer</a> implementations to be used in a ASP.NET Core web app for including AppCenter diagnostic information when logging to Application Insights
<br />
<br />
Enabling this is easy. Assuming that the project is already configured to use Application Insights, just add the <a href="https://www.nuget.org/packages/AppCenterExtensions.AppInsights">AppCenterExtensions.AppInsights</a> NuGet package mentioned above to your ASP.NET Core and call <b>services.AddAppCenterTelemetry()</b> in the <b>ConfigureServices</b> method of the <b>Startup</b> class<br />
<br />
Here's an example:<br />
<br />
<pre><code><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">Startup</span>
{
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Startup</span>(<span class="hljs-params">IConfiguration configuration</span>)
</span>{
Configuration = configuration;
}
<span class="hljs-keyword">public</span> IConfiguration Configuration { <span class="hljs-keyword">get</span>; }
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">ConfigureServices</span>(<span class="hljs-params">IServiceCollection services</span>)
</span>{
<span class="hljs-comment">// Configure and register services to the IoC</span>
services.AddApplicationInsightsTelemetry();
services.AddAppCenterTelemetry();
}
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">Configure</span>(<span class="hljs-params">IApplicationBuilder app, IWebHostEnvironment env</span>)
</span>{
<span class="hljs-comment">// Configure app</span>
}
}
</code></pre>
<br />
Once this is setup, AppCenter diagnostic information should now be searchable and visible in Application Insights.<br />
<br />
Here's a screenshot of search results for the <strong>x-supportkey</strong> header<br />
<br />
<img alt="" height="491" src="https://github.com/christianhelle/appcenterextensions/blob/master/images/appinsights-search-result.png?raw=true" width="640" /><br />
<br />
and here's a screenshot of the details of a single request containing AppCenter diagnostic information logged in Application Insights<br />
<br />
<img alt="" height="489" src="https://github.com/christianhelle/appcenterextensions/blob/master/images/appinsights-search-result-details.png?raw=true" width="640" /><br />
<br />
With this flow you can now correlate Crash Reports and Analytics data from AppCenter with the HTTP requests for your backend systems in Application Insights. In the systems that I have been involved with building we include the AppCenter diagnostic information from our <a href="https://docs.microsoft.com/en-us/dotnet/architecture/microservices/architect-microservice-container-applications/direct-client-to-microservice-communication-versus-the-api-gateway-pattern">API Gateway</a> to all calls to our internal Microservices<br />
<br />Christian Hellehttp://www.blogger.com/profile/16523297321435081745noreply@blogger.com0tag:blogger.com,1999:blog-4995334164049002857.post-3201385345713515622020-02-25T00:51:00.000+01:002020-03-01T21:32:39.571+01:00AppCenter Extensions for Xamarin.FormsFor the past 3 years or so I have been AppCenter for Crash Reporting and Analytics in Xamarin based apps. During this time, I have mostly built enterprise focused apps using Xamarin.Forms and as a developer I always think about code reuse which usually comes in the form of a library. Early this year, I decided to create and open source a set of convenience classes and extension methods to simplify Crash Reporting and Analytics using AppCenter and called it <b><a href="https://github.com/christianhelle/appcenterextensions">AppCenterExtensions</a></b>.<br />
<br />
The core features of the project are the following:<br />
<ul>
<li>Simplified user interaction reporting using <code>ICommand</code> implementations</li>
<li>Automatic page tracking in <strong>Xamarin.Forms</strong> including time spent on screen</li>
<li>Extension methods for crash reporting</li>
<li>Anonymous user information configuration</li>
</ul>
This library is distributed as 2 NuGet packages<br />
<ul>
<li><a href="https://www.nuget.org/packages/appcenterextensions">AppCenterExtensions</a> - This contains extension methods, <code>ICommand</code> implementations, and convenience classes for initializing and configuring AppCenter. This package depends on <a href="https://www.nuget.org/packages/Microsoft.AppCenter.Analytics/">Microsoft.AppCenter.Analytics</a> and <a href="https://www.nuget.org/packages/Microsoft.AppCenter.Crashes/">Microsoft.AppCenter.Crashes</a> version 2.6.4</li>
<li><a href="https://www.nuget.org/packages/appcenterextensions.xamarinforms">AppCenterExtensions.XamarinForms</a> - This contains components required for automatic page tracking using <a href="https://github.com/xamarin/Xamarin.Forms">Xamarin.Forms</a>. This package depends on <a href="https://www.nuget.org/packages/appcenterextensions">AppCenterExtensions</a> and <a href="https://www.nuget.org/packages/Xamarin.Forms/">Xamarin.Forms</a> version 4.0.0</li>
</ul>
<b>Getting Started</b><br />
<br />
This library is configured almost the same way as the AppCenter SDK. You provide the AppCenter secrets, and specify whether to anonymize the user information. Both Crash Reporting and Analytics are <strong>always</strong> enabled when using <code>AppCenterSetup</code>.<br />
<br />
<pre><code>AppCenterSetup.Instance.<span class="hljs-literal">Start</span>(
<span class="hljs-string">"[iOS AppCenter secret]"</span>,
<span class="hljs-string">"[Android AppCenter secret]"</span>,
anonymizeAppCenterUser: <span class="hljs-literal">true</span>);
</code></pre>
or<br />
<pre><code><span class="hljs-keyword">await</span> AppCenterSetup.Instance.StartAsync(
<span class="hljs-string">"[iOS AppCenter secret]"</span>,
<span class="hljs-string">"[Android AppCenter secret]"</span>,
anonymizeAppCenterUser: <span class="hljs-literal">true</span>);
</code></pre>
<br />
The reason for the <code>async</code> API here is because <code>anonymizeAppCenterUser</code> internally relies on an <code>async</code> API. The synchronous API's for starting AppCenter are non-blocking methods that do a fire-and-forget call to <code>StartAsync(string,bool)</code>.<br />
<b><br />
</b> <b>Anonymous User Information</b><br />
<b><br />
</b> The component <code>AppCenterSetup</code> exposes a method called <code>UseAnonymousUserIdAsync()</code> which sets the UserId in AppCenter to the first 8 characters a GUID that is unique per app installation. This can be used as a <strong>support key</strong> for uniquely identifying application users for instrumentation and troubleshooting. The <strong>support key</strong> can be attached to all HTTP calls by using the <code>DiagnosticDelegatingHandler</code><br />
<code><br />
</code> <img alt="AppCenter Crash Report" height="640" src="https://github.com/christianhelle/appcenterextensions/blob/master/images/appcenter-crash-report.png?raw=true" width="624" /><br />
<b><br />
</b> <b>Error Reporting</b><br />
<b><br />
</b> The library exposes extension methods to the <code>Exception</code> class for conveniently reporting Exceptions to AppCenter<br />
<br />
Example:<br />
<pre><code><span class="hljs-selector-tag">try</span>
{
<span class="hljs-comment">// Something that blows up</span>
<span class="hljs-selector-tag">explosives</span><span class="hljs-selector-class">.Detonate</span>();
}
<span class="hljs-selector-tag">catch</span> (Exception e)
{
<span class="hljs-comment">// Safely handle error then report</span>
<span class="hljs-selector-tag">e</span><span class="hljs-selector-class">.Report</span>();
}<b>
</b></code></pre>
<b><br />
</b> <b>HTTP Error Logging</b><br />
<b><br />
</b> The library provides a <code>HttpMessageHandler</code> implementation that logs non-successfuly HTTP results to AppCenter Analytics. This component will also attach HTTP headers describing the AppCenter SDK Version, Install ID, and a support key to all HTTP requests. The logged failed responses will contain the Endpoint URL (including the HTTP verb), Response status code, how the duration of the HTTP call. This will be logged under the event name <strong>HTTP Error</strong><br />
<strong><br />
</strong> You will in most (if not all) cases would want to keep a singleton instance of the <code>HttpClient</code>. The <code>DiagnosticDelegatingHandler</code> is designed with unit testing in mind and accepts an <code>IAnalytics</code> and <code>IAppCenterSetup</code> interface, it also accepts an inner <code>HttpMessageHandler</code> if you wish to chain multiple delegating handlers.<br />
<br />
Example:<br />
<pre><code><span class="hljs-keyword">var</span> httpClient = <span class="hljs-keyword">new</span> <span class="hljs-type">HttpClient</span>(<span class="hljs-keyword">new</span> <span class="hljs-type">DiagnosticDelegatingHandler</span>());
await httpClient.GetAsync(<span class="hljs-string">"https://entbpr4b9bdpo.x.pipedream.net/"</span>);
</code></pre>
<br />
In the example above we made an HTTP GET call to the <a href="https://requestbin.com/">RequestBin</a> endpoint <a href="https://entbpr4b9bdpo.x.pipedream.net/">https://entbpr4b9bdpo.x.pipedream.net</a>. This will result in the following we inspected in <a href="https://requestbin.com/r/entbpr4b9bdpo/1XO0uroL0xZlDfvPNKlFBZaRLo0">RequestBin</a><br />
<br />
<img alt="AppCenter Crash Report" height="193" src="https://github.com/christianhelle/appcenterextensions/blob/master/images/http-diagnostic-headers.png?raw=true" width="640" /><br />
<b><br />
</b> <b>ITrackingCommand</b><br />
<b><br />
</b> This library provides 3 convenience implementations of <code>ICommand</code> that will report the action to AppCenter Analytics after successfully invoking the execute callback method<br />
<ul>
<li><strong><em>TrackingCommand</em></strong> - This implementation accepts an <code>Action</code> as the Execute callback and a <code>Func<bool></code> as the CanExecute callback</li>
<li><strong><em>TrackingCommand<t></t></em></strong> - This implementation accepts an <code>Action<T></code> as the Execute callback and a <code>Func<T, bool></code> as the CanExecute callback</li>
<li><strong><em>AsyncTrackingCommand</em></strong> - This implementation accepts a <code>Func<Task></code> as the execute callback and a <code>Func<bool></code> as the CanExecute callback. This also exposes a <code>CompletionTask</code> property that the consumer can <code>await</code> if desired. The <code>Execute(object parameter)</code> method here is a non-blocking call</li>
</ul>
Example:<br />
<pre><code><span class="hljs-keyword">using</span> System.Threading.Tasks;
<span class="hljs-keyword">using</span> System.Windows.Input;
<span class="hljs-keyword">using</span> ChristianHelle.DeveloperTools.AppCenterExtensions.Commands;
<span class="hljs-keyword">using</span> ChristianHelle.DeveloperTools.AppCenterExtensions.Extensions;
<span class="hljs-keyword">using</span> Microsoft.AppCenter.Crashes;
<span class="hljs-keyword">using</span> Xamarin.Essentials;
<span class="hljs-keyword">namespace</span> <span class="hljs-title">SampleApp.ViewModels</span>
{
<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">AboutViewModel</span> : <span class="hljs-title">BaseViewModel</span>
{
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">AboutViewModel</span>(<span class="hljs-params"></span>)
</span>{
AsyncButtonTappedCommand = <span class="hljs-keyword">new</span> AsyncTrackingCommand(
OnAsyncButtonTapped,
<span class="hljs-keyword">nameof</span>(AsyncButtonTappedCommand).ToTrackingEventName(),
<span class="hljs-keyword">nameof</span>(AboutViewModel).ToTrackingEventName());
ButtonOneTappedCommand = <span class="hljs-keyword">new</span> TrackingCommand(
OnButtonOneTapped,
<span class="hljs-keyword">nameof</span>(ButtonOneTappedCommand).ToTrackingEventName(),
<span class="hljs-keyword">nameof</span>(AboutViewModel).ToTrackingEventName());
ButtonTwoTappedCommand = <span class="hljs-keyword">new</span> TrackingCommand<<span class="hljs-keyword">string</span>>(
OnButtonTapped,
<span class="hljs-keyword">nameof</span>(ButtonTwoTappedCommand).ToTrackingEventName(),
<span class="hljs-keyword">nameof</span>(AboutViewModel).ToTrackingEventName());
}
<span class="hljs-keyword">public</span> ICommand AsyncButtonTappedCommand { <span class="hljs-keyword">get</span>; }
<span class="hljs-keyword">public</span> ICommand ButtonOneTappedCommand { <span class="hljs-keyword">get</span>; }
<span class="hljs-keyword">public</span> ICommand ButtonTwoTappedCommand { <span class="hljs-keyword">get</span>; }
<span class="hljs-function"><span class="hljs-keyword">private</span> Task <span class="hljs-title">OnAsyncButtonTapped</span>(<span class="hljs-params"></span>)
</span>=> Browser.OpenAsync(<span class="hljs-string">"https://xamarin.com"</span>);
<span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">OnButtonOneTapped</span>(<span class="hljs-params"></span>) </span>{ }
<span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">OnButtonTwoTapped</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> obj</span>) </span>{ }
}
}
</code></pre>
<br />
Specifying the <code>screenName</code> argument in the constructor is optional and when this is not provided manually then it will use the declaring <code>Type</code> name from the method that instantiated the <code>ITrackingCommand</code> instance and convert it to a more analytics friendly event name using the <code>ToTrackingEventName()</code> extension method. In the example above, if the <code>nameof(AboutViewModel).ToTrackingEventName()</code> parameter is not provided then the owner declaring Type is <code>AboutViewModel</code> and the <code>ScreenName</code> will be set to <code>"About"</code><br />
<b><br />
</b> <b>Automatic Page Tracking</b><br />
<b><br />
</b> Automatic page tracking is enabled by replacing the base class of the <code>ContentPage</code> to classes to use <code>TrackingContentPage</code> class. By doing so the library will send page tracking information to AppCenter after leaving every page. Currently, the library will send the page Type, Title, and the duration spent on the screen. The library is rather opinionated on how to log information, and this will only change if I get a request to do so. Duration spent on screen is calculated using a <code>Stopwatch</code> that is started upon Page <code>OnAppearing</code> and is reported to Analytics upon <code>OnDisappearing</code>. The event name is based on the <code>Type</code> name of the <code>Page</code> and is split into multiple words based on pascal case rules and afterwards removes words like <code>Page</code>, <code>View</code>, <code>Model</code>, <code>Async</code>. For example: <code>UserSettingsPage</code> or <code>UserSettingsView</code> becomes <strong>User Settings</strong><br />
<strong><br />
</strong> XAML Example:<br />
<pre><code><?xml version=<span class="hljs-string">"1.0"</span> encoding=<span class="hljs-string">"utf-8"</span>?>
<ext:TrackingContentPage
xmlns=<span class="hljs-string">"http://xamarin.com/schemas/2014/forms"</span>
xmlns:x=<span class="hljs-string">"http://schemas.microsoft.com/winfx/2009/xaml"</span>
xmlns:d=<span class="hljs-string">"http://xamarin.com/schemas/2014/forms/design"</span>
xmlns:mc=<span class="hljs-string">"http://schemas.openxmlformats.org/markup-compatibility/2006"</span>
xmlns:ext=<span class="hljs-string">"clr-namespace:AppCenterExtensions.XamarinForms;assembly=AppCenterExtensions.XamarinForms"</span>
mc:Ignorable=<span class="hljs-string">"d"</span>
x:Class=<span class="hljs-string">"SampleApp.Views.ItemDetailPage"</span>
Title=<span class="hljs-string">"{Binding Title}"</span>>
<StackLayout Spacing=<span class="hljs-string">"20"</span> <span class="hljs-keyword">Padding</span>=<span class="hljs-string">"15"</span>>
<<span class="hljs-keyword">Label</span> <span class="hljs-keyword">Text</span>=<span class="hljs-string">"Text:"</span> <span class="hljs-keyword">FontSize</span>=<span class="hljs-string">"Medium"</span> />
<<span class="hljs-keyword">Label</span> <span class="hljs-keyword">Text</span>=<span class="hljs-string">"{Binding Item.Text}"</span> d:<span class="hljs-keyword">Text</span>=<span class="hljs-string">"Item name"</span> <span class="hljs-keyword">FontSize</span>=<span class="hljs-string">"Small"</span> />
<<span class="hljs-keyword">Label</span> <span class="hljs-keyword">Text</span>=<span class="hljs-string">"Description:"</span> <span class="hljs-keyword">FontSize</span>=<span class="hljs-string">"Medium"</span> />
<<span class="hljs-keyword">Label</span> <span class="hljs-keyword">Text</span>=<span class="hljs-string">"{Binding Item.Description}"</span> d:<span class="hljs-keyword">Text</span>=<span class="hljs-string">"Item description"</span> <span class="hljs-keyword">FontSize</span>=<span class="hljs-string">"Small"</span> />
</StackLayout>
</ext:TrackingContentPage><b>
</b></code></pre>
<b><br />
</b> <b>Custom Trace Listener</b><br />
<b><br />
</b> This library includes a trace listener implementation that reports to AppCenter. The reason for this is to cater to those who have implemented error handling or reporting using Trace Listeners, these types of users can just swap out (or add on) the <code>AppCenterTraceListener</code><br />
<code><br />
</code> This implementation implements the following methods:<br />
<ul>
<li><code>Write(object obj)</code></li>
<li><code>Write(object obj, string category)</code></li>
<li><code>WriteLine(object obj)</code></li>
<li><code>WriteLine(object obj, string category)</code></li>
</ul>
If the <code>object</code> provided is an <code>Exception</code> then this is reported to AppCenter Crash Reporting. If the <code>object</code> provided is an instance of <code>AnalyticsEvent</code> then this is sent to AppCenter Analytics<br />
<br />
The <code>AnalyticsEvent</code> exposes 2 properties:<br />
<ul>
<li><code>string EventName { get; }</code> - self explanatory</li>
<li><code>IDictionary<string,string> Properties { get; }</code> - Additional properties to attach to the Analytics event</li>
</ul>
To set it up you simply add an instance of <code>AppCenterTraceListener</code> to your existing Trace listeners:<br />
<pre><code><span class="hljs-selector-tag">Trace</span><span class="hljs-selector-class">.Listeners</span><span class="hljs-selector-class">.Add</span>(<span class="hljs-selector-tag">new</span> <span class="hljs-selector-tag">AppCenterTraceListener</span>());
</code></pre>
<br />
Here's an example of how to use <code>System.Diagnostics.Trace</code> to report errors<br />
<pre><code><span class="hljs-keyword">try</span>
{
<span class="hljs-comment">// Something that blows up</span>
explosives.Detonate();
}
<span class="hljs-keyword">catch</span> (Exception e)
{
<span class="hljs-comment">// Safely handle error then report</span>
Trace.<span class="hljs-keyword">Write</span>(e);
<span class="hljs-comment">// or</span>
Trace.<span class="hljs-keyword">Write</span>(e, <span class="hljs-string">"Error"</span>);
<span class="hljs-comment">// or</span>
Trace.<span class="hljs-keyword">WriteLine</span>(e);
<span class="hljs-comment">// or</span>
Trace.<span class="hljs-keyword">WriteLine</span>(e, <span class="hljs-string">"Error"</span>);
}
</code></pre>
and here's an example of to use <code>System.Diagnostics.Trace</code> to send analytics data<br />
<pre><code><span class="hljs-keyword">public</span> <span class="hljs-keyword">partial</span> <span class="hljs-keyword">class</span> <span class="hljs-title">App</span> : <span class="hljs-title">Application</span>
{
<span class="hljs-keyword">private</span> <span class="hljs-keyword">const</span> <span class="hljs-keyword">string</span> StateKey = <span class="hljs-string">"State"</span>;
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>)
</span>{
<span class="hljs-comment">// Some initialization code ...</span>
Trace.Listeners.Add(<span class="hljs-keyword">new</span> AppCenterTraceListener());
}
<span class="hljs-function"><span class="hljs-keyword">protected</span> <span class="hljs-keyword">override</span> <span class="hljs-keyword">void</span> <span class="hljs-title">OnStart</span>(<span class="hljs-params"></span>)
</span>=> Trace.Write(
<span class="hljs-keyword">new</span> AnalyticsEvent(
<span class="hljs-keyword">nameof</span>(Application),
<span class="hljs-keyword">new</span> Dictionary<<span class="hljs-keyword">string</span>, <span class="hljs-keyword">string</span>>
{
{ StateKey, <span class="hljs-keyword">nameof</span>(OnStart) }
}));
<span class="hljs-function"><span class="hljs-keyword">protected</span> <span class="hljs-keyword">override</span> <span class="hljs-keyword">void</span> <span class="hljs-title">OnSleep</span>(<span class="hljs-params"></span>)
</span>=> Trace.Write(
<span class="hljs-keyword">new</span> AnalyticsEvent(
<span class="hljs-keyword">nameof</span>(Application),
<span class="hljs-keyword">new</span> Dictionary<<span class="hljs-keyword">string</span>, <span class="hljs-keyword">string</span>>
{
{ StateKey, <span class="hljs-keyword">nameof</span>(OnSleep) }
}));
<span class="hljs-function"><span class="hljs-keyword">protected</span> <span class="hljs-keyword">override</span> <span class="hljs-keyword">void</span> <span class="hljs-title">OnResume</span>(<span class="hljs-params"></span>)
</span>=> Trace.Write(
<span class="hljs-keyword">new</span> AnalyticsEvent(
<span class="hljs-keyword">nameof</span>(Application),
<span class="hljs-keyword">new</span> Dictionary<<span class="hljs-keyword">string</span>, <span class="hljs-keyword">string</span>>
{
{ StateKey, <span class="hljs-keyword">nameof</span>(OnResume) }
}));
}<b>
</b></code></pre>
<b><br />
</b> <b>Task Extensions</b><br />
<b><br />
</b> This library includes a few Task extension methods with AppCenter error reporting in mind. Possible exceptions that occur in the async operation are swallowed and reported to AppCenter. These extension methods will internally wrap the Task in a <code>try/catch</code> and <code>await</code> the Task using <code>ConfigureAwait(false)</code>. <br />
<br />
Here are usage some examples<br />
<br />
<div style="display: inline !important;">
Fire and Forget on a <code>Task</code> (Note: <code>Forget()</code> returns <code>void</code>)</div>
<div>
<pre><span class="hljs-keyword">var</span> <span class="hljs-keyword">task</span> = someClass<span class="hljs-variable">.SomethingAsync</span>()
<span class="hljs-keyword">task</span><span class="hljs-variable">.Forget</span>()</pre>
<div style="display: inline !important;">
</div>
<div>
<div style="display: inline !important;">
<br /></div>
</div>
Awaitable <code>Task</code> (also available for <code>Task<T></code>)<br />
<div>
<pre><span class="hljs-keyword">var</span> <span class="hljs-keyword">task</span> = someClass<span class="hljs-variable">.SomethingAsync</span>()
await <span class="hljs-keyword">task</span><span class="hljs-variable">.WhenErrorReportAsync</span>();</pre>
<pre></pre>
</div>
</div>
Christian Resma Hellehttp://www.blogger.com/profile/16521776612083091477noreply@blogger.com0tag:blogger.com,1999:blog-4995334164049002857.post-12486804333544445962019-06-26T22:30:00.001+02:002019-06-26T22:35:34.121+02:00Generate Android Translations from Google SheetsIn previous articles <a href="https://christian-helle.blogspot.com/2019/06/generate-resx-translations-using-google.html" target="_blank">Generating ResX translations from Google Sheets</a> and <a href="https://christian-helle.blogspot.com/2019/06/generate-ios-infopliststrings.html" target="_blank">Generate iOS InfoPlist.strings Translations from Google Sheets</a>, I wrote about using Google Sheets as a translation tool by using the <a href="https://support.google.com/docs/answer/3093331?hl=en" target="_blank">GOOGLETRANSLATE</a> built in function to generate translation files for a <b>Xamarin</b> based solution. For this post, I will demonstrate something very similar, but instead of ResX files or InfoPlist.strings, I'll generate <b>strings.xml</b> files for Android. For the sake of this article I created <a href="https://docs.google.com/spreadsheets/d/1mrMkhItrIDsPwEKMlR8JJ3Pgj1K6zUv0AhmBT4jWRqs/edit#gid=0" target="_blank">this sample Google Sheets</a><br />
<br />
For a quick recap, we will use a tool called <a href="https://github.com/rickykaare/csvtrans" target="_blank">csvtrans</a> written by my colleague and good friend, <a href="https://twitter.com/rickykaare" target="_blank">Ricky Kaare Engelharth</a>. The tool is built with .NET Core and can be installed using this command<br />
<pre><code>
<b>dotnet tool install -g csvtrans</b>
</code>
</pre>
Using the tool is also straight forward and it also comes with some quick start instructions<br />
<pre><code>
<b>USAGE: csvtrans [--help] [--sheet <document id> <sheet name>]
[--csv <url or path>] [--format <apple|android|resx>]
[--outputdir <directory path>] [--name <string>]
[--convert-placeholders <regex pattern>]
OPTIONS:
--sheet, -s <document id> <sheet name>
specify a Google Sheet as input.
--csv, -c <url or path>
specify a online or local cvs file as input.
--format, -f <apple|android|resx>
specify the output format.
--outputdir, -o <directory path>
specify the output directory.
--name, -n <string> specify an optional name for the output.
--convert-placeholders, -p <regex pattern>
convert placeholders to match the output format.
--help display this list of options.</b>
</code></pre>
<br />
Here's an example usage of tool
<br />
<pre><code>
<b>csvtrans --sheet 1mrMkhItrIDsPwEKMlR8JJ3Pgj1K6zUv0AhmBT4jWRqs Android --format android --outputdir .\Resources\</b>
</code>
</pre>
The first argument <code><b>–-sheet</b></code> is the Google Sheet document ID followed by the Sheet Name, the next argument <code><b>–-format</b></code> specifies the output file format, and the last argument <code><b>–-outputdir</b></code> specifies the output folder<br />
<br />
You can get the Document ID from the URL of the Google Sheet<br />
<br />
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhTUoZ4e3ySL1SZ_BbN1zVD1qtDgNg5g1saSgxptTH_b6DVqUKTS3cDa-zIsSZEi_koz6yhlXs0flOHgdPs4UxjmkEFdGPDCGN1ezawlH8dCIZmDqQY6zlnLIW9F_rByfkOT7K0DOcQmk0/s1600/sheets-android.png" />
<br />
<br />
Here's an example output
<br />
<br />
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSlqg_dyAe0BdVN5Gyf3YOKCj3NdS7k2EjlI2vO28k4Zo1HBwX35jmD7vQ9_ooLlj3EKeU02b1Wt0C7aYEyiLF1jhtApWvQodunHIBlrDt1yWGG_BxDbo3RUVcBusrEk437mhVMDZdhNA/s1600/csvtrans-android.png" />
<br />
<br />
Now I can just bring these files into my project and use them directly. Well, almost! There's one little problem, and that is that by default the <b>Xamarin.Android</b> csproj tooling explicitly adds each <b>strings.xml</b> file as an <b>AndroidResource</b>. Oddly enough, the csproj format allows to specify wild card folders, so if we want to enable dynamic generation of <b>values/strings.xml</b> translations then we need to manually edit the csproj.
<br />
<br />
This is actually very easy to do. We just need to replace the lines like
<br />
<br />
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjq7sUJRCDAc6Hpz90aBARHUJUJLs33veyG-mpNuLTgTm93RNCoVzj6oZW8gN9vDIrpJVK-Ai6YgQjhsLKfTKOJuscqVs930_ge5rvA0_0WgYmt-DoZ1_2dkZC3Ir5dLf8_evtr1mVS60E/s1600/android-csproj-before.png" />
<br />
<br />
with
<br />
<br />
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhDPj18cTk5KyxapQPjG9sflnnbKTxL6r9mYu2IpZSAnTb7OGLdrlRuePUzS6IXjCIlcj4i2oMn5A7SG081E-BipmRK1OHuWPfzQClIWT9piqk87UJTrqz7i6B0hBU4SzM3SFpo0MDNJYg/s1600/android-csproj-after.png" />
<br />
<br />
This opens up for dynamic translations at build time using your CI/CD build tools of choiceChristian Hellehttp://www.blogger.com/profile/16523297321435081745noreply@blogger.com0tag:blogger.com,1999:blog-4995334164049002857.post-62064538541702116642019-06-18T23:21:00.001+02:002019-06-20T16:55:49.393+02:00Generate iOS InfoPlist.strings Translations from Google SheetsIn my previous article <a href="https://christian-helle.blogspot.com/2019/06/generate-resx-translations-using-google.html">Generating ResX translations from Google Sheets</a>, I wrote about using Google Sheets as a translation tool by using the <a href="https://support.google.com/docs/answer/3093331?hl=en">GOOGLETRANSLATE</a> built in function to generate translation files for a <b>Xamarin.Forms</b> solution. For this post, I will demonstrate something very similar, but instead of ResX files I'll generate <b>InfoPlist.strings</b> files in iOS for localizing the permission request prompts for accessing things like Camera, Location, Photo Gallery, etc. For the sake of this article I created <a href="https://docs.google.com/spreadsheets/d/125id155PUq-6Odwg8Nf9fmkgBsKahTGbJYaYBD2rpSg">this sample Google Sheets</a>
<br />
<br />
For a quick recap, we will use a tool called <a href="https://github.com/rickykaare/csvtrans">csvtrans</a> written by my colleague and good friend, <a href="https://twitter.com/rickykaare">Ricky Kaare Engelharth</a>. The tool is built with .NET Core and can be installed using this command<br />
<pre><code>
<b>dotnet tool install -g csvtrans</b>
</code>
</pre>
Using the tool is also straight forward and it also comes with some quick start instructions<br />
<pre><code>
<b>USAGE: csvtrans [--help] [--sheet <document id> <sheet name>]
[--csv <url or path>] [--format <apple|android|resx>]
[--outputdir <directory path>] [--name <string>]
[--convert-placeholders <regex pattern>]
OPTIONS:
--sheet, -s <document id> <sheet name>
specify a Google Sheet as input.
--csv, -c <url or path>
specify a online or local cvs file as input.
--format, -f <apple|android|resx>
specify the output format.
--outputdir, -o <directory path>
specify the output directory.
--name, -n <string> specify an optional name for the output.
--convert-placeholders, -p <regex pattern>
convert placeholders to match the output format.
--help display this list of options.</b>
</code></pre>
<br />
Here’s an example usage of the tool<br />
<pre><code>
<b>csvtrans --sheet 125id155PUq-6Odwg8Nf9fmkgBsKahTGbJYaYBD2rpSg iOS --format apple --outputdir .\Resources --name InfoPlist</b>
</code></pre>
<br />
The first argument <code><b>–-sheet</b></code> is the Google Sheet document ID followed by the Sheet Name, the next argument <code><b>–-format</b></code> specifies the output file format, the argument <code><b>–-outputdir</b></code> specifies the output folder, and the last argument <code><b>--name</b></code> specifies the output filename.<br />
<br />
You can get the Document ID from the URL of the Google Sheet<br />
<br />
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhB0y2fofj9Fs_nxj0-0S88z1Cg2qUmWKvjfH80dSkFGoxgq6O_u-1MrQCaKm9sF7X6O2dEXUDNI7I5Vs4vc4-91BEyLh_auxQ_FTAvONPiQnB7hHokm1ouyS56Hk0GlJpLMM4kxMgHNg0/s1600/infoplist-google-sheets.png" />
<br />
<br />
Here's an example output
<br />
<br />
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0TTSyJNBDCpv8tnFnPkalXZ7NWSA3crd0dIxI527oZH3VE3RoBexhIMMhsbhV2WWxSRpbSv6V4zoYQ74fs_trpwgIjjfosYRD_u53VZk3m9_dPGeXN9hq9QI1_ML9tzyemofTcBkz5NY/s1600/infoplist-console.png" />
<br />
<br />
Now I can just bring these files into my project and use them directly. Well, almost! There's one little problem, and that is that by default the <b>Xamarin.iOS</b> csproj tooling explicitly adds each <b>InfoPlist.strings</b> file as a <b>BundleResource</b>. Oddly enough, the csproj format allows to specify wild card folders, so if we want to enable dynamic generation of InfoPlist.strings translations then we need to manually edit the csproj.
<br />
<br />
This is actually very easy to do. We just need to replace the lines like
<br />
<br />
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi60Jam0xQJazxXaCaQ8yoIJTyRgZBnNTiO1hJCvxFBBGyLpDWCguAfN3ZTG5dBLkEBtfzv8vR6hnKLDjNPfLJNm1GqcWTBVREWAgKa73eE7FHpUOLgMq-_Q_GEi9tsr-a34BAVcFTLlEU/s1600/csproj-before.png" />
<br />
<br />
with
<br />
<br />
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_FxKCcvAJ1uZztKXqbUcHV-IRpDgebhBKy7jkC7cXg-CVRTUEVWFGGb9bc9BKUgUuH4p4Z47TvZkQamgEn-LTtkCjhvGyWZuqEmFJ1K4ncv3xfK-yo1i_IM4d-daCkFIk_EPRsV9L5H0/s1600/csproj-after.png" />
<br />
<br />
This opens up for dynamic translations at build time using your CI/CD build tools of choice<br />
<br />Christian Hellehttp://www.blogger.com/profile/16523297321435081745noreply@blogger.com0tag:blogger.com,1999:blog-4995334164049002857.post-40895914797277414532019-06-12T22:30:00.002+02:002019-06-13T09:28:50.488+02:00Generate Resx Translations from Google SheetsIn my career, I have tried multiple translation tools for handling localization. This usually ends up in a spreadsheet sent back and forth that gets imported/exported with the actual translation tool. I have also tried giving my translators and customers direct access to the translation tool but that never really worked as they tend to blindly translate everything they see and usually miss out on the fact that some strings contain important placeholders that executable code expects. Anyway, at the end of the sending a spreadsheet back and forth seems to always work.<br />
<br />
In a recent project, I built an Android and iOS app with Xamarin.Forms that used Resx files for handling cross platform translations, and InfoPlist.strings files in iOS for localizing OS requirement prompts for using things like Camera, Localization, Photos, etc. For this project we thought about playing around with Google Sheets as a translation tool. Google Sheets has built in Google Translate support so you can do something like <b>=GOOGLETRANSLATE($B2,$B$1,C$1)</b> where <b>$B2</b> describes the text to translate, <b>$B1</b> describes the source language, in this case English is the default, and<b> $C1</b> describes the language to translate to. With this approach, I can very easily, blindly, add new translations to my app, like in <a href="http://docs.google.com/spreadsheets/d/1icJ0a48MIIRkbHSIbPyLNXsbTZcPKI_U80QwdX5pWf8">this sample</a> Google Sheets document, where I added Danish, German, Filipino, Simplified Chinese, Japanese, and Koreanusing the Google Translate tool. Of course, this needs to be proof-read by a translation professional who mastered the language, but this approach is very convenient for checking out how the app looks like in different languages.<br />
<br />
Now here’s the awesome part. My colleague and good friend, <a href="https://twitter.com/rickykaare">Ricky Kaare Engelharth</a>, created a translation tool called <a href="https://github.com/rickykaare/csvtrans">csvtrans </a>that can produce Resx, iOS, and Android translation files from a publicly available Google Sheets document. The tool is written in .NET Core and is publicly available from <a href="https://www.nuget.org/packages/csvtrans">nuget.org</a> as a tool.<br />
<br />
The tool can be installed using this command<br />
<pre><code>
<b>dotnet tool install -g csvtrans</b>
</code>
</pre><br />
Using the tool is also straight forward and it also comes with some quick start instructions<br />
<pre><code>
<b>USAGE: csvtrans [--help] [--sheet <document id> <sheet name>]
[--csv <url or path>] [--format <apple|android|resx>]
[--outputdir <directory path>] [--name <string>]
[--convert-placeholders <regex pattern>]
OPTIONS:
--sheet, -s <document id> <sheet name>
specify a Google Sheet as input.
--csv, -c <url or path>
specify a online or local cvs file as input.
--format, -f <apple|android|resx>
specify the output format.
--outputdir, -o <directory path>
specify the output directory.
--name, -n <string> specify an optional name for the output.
--convert-placeholders, -p <regex pattern>
convert placeholders to match the output format.
--help display this list of options.</b>
</code></pre><br />
Here’s an example usage of the tool<br />
<pre><code>
<b>csvtrans --sheet 1icJ0a48MIIRkbHSIbPyLNXsbTZcPKI_U80QwdX5pWf8 Resx --format resx --outputdir .\Resources</b>
</code></pre><br />
The first argument <code><b>–-sheet</b></code> is the Google Sheet document ID followed by the Sheet Name, the next argument <code><b>–-format</b></code> specifies the output file format, and the last argument <code><b>–-outputdir</b></code> specifies the output folder.<br />
<br />
You can get the Document ID from the URL of the Google Sheet<br />
<br />
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh80QTnDUSBMm48msLAGgbb-0NahTIXSGcKmV-N3ycjnVXeCoQ3dbtB-UnAClWB3F9EBaTpTuKSoKGOhYr5dAWUbWSTEnN-BmMLOdWk5KysE6x8mZeUqqC0QtnfwHIWlkn-odfrMDV1Y-85/s1600/GoogleSheets.png" /><br />
<br />
Here's an example output<br />
<br />
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUKtP5mrA4-9H827mMCEIjrhsMQX-pmW3LCHR3fa0u-YOFnwL5nXwtZu6Fsl_lx1EUUMSKLRmRr7l9rBLnGbOv6AaQM4y5-xesG8g1pEdCWLglmGki0Py7srsTzwBGwfdzwxJh2l0hu0vL/s1600/csvtrans-output.png" /><br />
<br />
Now I can just bring these files into my project and use them directly. With the modern csproj format I don't even need to do any changes to include these translation files, as long as the resx files are in the project folder they will be automagically included into the output. This opens up for dynamic translations at build time using your CI/CD build tools of choiceChristian Resma Hellehttp://www.blogger.com/profile/16521776612083091477noreply@blogger.com0tag:blogger.com,1999:blog-4995334164049002857.post-11680522972257654852019-06-09T14:52:00.005+02:002019-06-11T18:54:11.769+02:00Scrollable UISegmentedControl for Xamarin.iOSA few years ago, I had a full time job as a device developer in the Music Streaming industry. The applications we produced at the time targeted consumers and had a huge focus on UX and UI. One of the requirements our designers had was to have scrollable tabs. This was 5 years ago and before <a href="https://docs.microsoft.com/en-us/xamarin/xamarin-forms/">Xamarin.Forms</a> existed so we built the <a href="http://itunes.apple.com/dk/app/yousee-musik/id1108892163" target="_blank">iOS app</a> and <a href="http://play.google.com/store/apps/details?id=dk.yousee.musik" target="_blank">Android app</a> separately. We used <a href="https://www.mvvmcross.com/">MvvmCross</a> and the shared a lot of core code but the UI components were done per OS. When we started, the company did a recent switch to go full on with .NET on everything, so not only did we share code between apps, but we shared code across all systems within the entire organization.<br />
<br />
Scrollable tabs come for free in Android using the built-in control <a href="https://developer.android.com/reference/android/support/design/widget/TabLayout">TabLayout </a>but on iOS we needed to re-create the <a href="https://developer.apple.com/documentation/uikit/uisegmentedcontrol" target="_blank">UISegmentedControl</a> and add scroll/pan/swipe functionality to it. On native code, you had a few options to choose from, so the first task was to find the best native implementation of it and port it to C#. A few Google searches later I found the <a href="https://github.com/HeshamMegid/HMSegmentedControl" target="_blank">HMSegmentedControl</a> written by <a href="https://hesh.am/" target="_blank">Hesham Abd-Elmegid</a>. The component at the time was written in a single file and was a drop in replacement for the UISegmentedControl. It was functional, elegent, and directly portable to C#. It was perfect!<br />
<br />
A few hours of focused coding later I managed to port the entire thing to C# and created a <a href="https://github.com/christianhelle/ScrollableSegmentedControl" target="_blank">Github project</a> for it. I originally called it HMSegmentedControl as a tribute to the author (I also sent him a thank you email at the time) but later changed it to ScrollableSegmentedControl as it was a better and more descriptive name that states exactly what it does. Recently, I re-visited this project to clean up, modernize the code, and structure of the repository. I added a <a href="https://github.com/christianhelle/ScrollableSegmentedControl/blob/master/README.md">README </a>file with a useful description, screenshots, and code examples. I also published a <a href="https://www.nuget.org/packages/scrollablesegmentedcontrol" target="_blank">NuGet package</a> called <a href="https://www.nuget.org/packages/scrollablesegmentedcontrol">ScrollableSegmentedControl</a> to make it easier for others to use while keeping the responsibility of maintaining it.<br />
<br />
So using the component is quite trivial. Here's all you need to do:<br />
<br />
Add the ScrollableSegmentedControl <a href="https://www.nuget.org/packages/scrollablesegmentedcontrol">NuGet package</a><br />
<br />
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjF8aG3QC6nCnRXGw5_V_Alnd1wkhTdM-gmwc_FX5A0oUwmrcN9Jci_BlRpJVFzZgQ5J1-v92Mvz-UWSFT2O6kbMUeIok5KxkBK8mQtZbky_R4Np4FCy-nVFsh0jn28E-3QE47gZoZNMLy9/s1600/scrollablesegmentedcontrol-nuget.png" /><br />
<br />
then you create an instance of <b>ScrollableSegmentedControl</b> and you add it to a View<br />
<br />
<pre style="line-height: 125%; margin: 0;"><span style="color: blue;">using</span> System;
<span style="color: blue;">using</span> ChristianHelle.Controls.iOS;
<span style="color: blue;">using</span> CoreGraphics;
<span style="color: blue;">using</span> UIKit;
<span style="color: blue;">namespace</span> ScrollableSegmentedControlSample
{
<span style="color: blue;">public</span> <span style="color: blue;">partial</span> <span style="color: blue;">class</span> <span style="color: #2b91af;">ViewController</span> : UIViewController
{
<span style="color: blue;">public</span> ViewController(IntPtr handle) : <span style="color: blue;">base</span>(handle)
{
}
<span style="color: blue;">public</span> <span style="color: blue;">override</span> <span style="color: blue;">void</span> ViewDidLoad()
{
<span style="color: blue;">base</span>.ViewDidLoad();
CreateScrollableSegmentedControl();
}
<span style="color: blue;">private</span> <span style="color: blue;">void</span> CreateScrollableSegmentedControl()
{
<span style="color: #2b91af;">var</span> sectionTitles = <span style="color: blue;">new</span>[] { <span style="color: #a31515;">"One"</span>, <span style="color: #a31515;">"Two"</span>, <span style="color: #a31515;">"Three"</span>, <span style="color: #a31515;">"Four"</span>, <span style="color: #a31515;">"Five"</span>, <span style="color: #a31515;">"Six"</span> };
View.AddSubview(<span style="color: blue;">new</span> ScrollableSegmentedControl(sectionTitles)
{
Font = UIFont.FromName(<span style="color: #a31515;">"STHeitiSC-Light"</span>, 18.0f),
Frame = <span style="color: blue;">new</span> CGRect(0, 60, View.Frame.Width, 40),
SegmentEdgeInset = <span style="color: blue;">new</span> UIEdgeInsets(0, 10, 0, 10),
SelectionStyle = ScrollableSegmentedControlSelectionStyle.FullWidthStripe,
SelectionIndicatorLocation = ScrollableSegmentedControlIndicatorLocation.Down
});
}
}
}
</pre><br />
This would result in a segmented control that looks like this:<br />
<br />
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0HsdNH-aJoySvr4CNTUG6OufsSIP-Dz5HDywv178wlR11Q4ky2IyM5EjAune7uWkuyIWU9f9tG3tDm7OX0joP6PA_wUir46nZvW5kro5GqbKuMZU6iyqyvDCi86n-_lFJuj3iJPZOuq0n/s1600/scrollablesegmentedcontrol.png" /><br />
<br />
and can look like one of these examples depending on the <b>SelectionStyle </b>and <b>SelectionIndicatorLocation</b><br />
<br />
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZYttwCJP9iZtAeiJijSKPTR5VcYnV34W4ewC-H3M2J78RnlDh7zquoUaE917deAf73dTGIuL2ZEKcNH8dtTOfPmCnRDezgSfioiD1sFWNOaEzchr2xvtrGZLMZfGseInsiAu4jq7gbGRI/s1600/scrollablesegmentedcontrol-dark.png" /><br />
<br />
This post is probably 5 years too late but since I just only recently made it publicly available as a NuGet package I thought I should write a short article about it. I hope you find this useful<br />
Christian Resma Hellehttp://www.blogger.com/profile/16521776612083091477noreply@blogger.com0tag:blogger.com,1999:blog-4995334164049002857.post-17866493724494793972019-05-28T18:06:00.002+02:002019-06-11T18:55:15.085+02:00Generating a REST API Client from Visual Studio 2017 and 2019For the past year or so, I have been doing a lot of development that involves producing an OpenAPI specification document from a .NET Core based REST API and generating client code using things like <a href="https://github.com/Azure/autorest" target="_blank">AutoRest</a>, <a href="https://github.com/swagger-api/swagger-codegen" target="_blank">Swagger Codegen</a>, <a href="https://github.com/OpenAPITools/openapi-generator" target="_blank">OpenAPI Codegen</a>, and <a href="https://github.com/RicoSuter/NSwag" target="_blank">NSwag</a>. My problem with these tools is that I often need to leave Visual Studio and quite often update the tool before I can re-generate my REST API client code. After doing this a couple of times I thought that I should just build a Visual Studio extension to make my life easier. At the end of last year I started work on a Visual Studio extension called the <a href="https://marketplace.visualstudio.com/items?itemName=ChristianResmaHelle.APIClientCodeGenerator" target="_blank">REST API Client Code Generator</a>,<span style="background-color: white; color: #191e23; font-family: "noto serif"; font-size: 16px; white-space: pre-wrap;"> A collection of Visual Studio custom tools for generating a strongly typed REST API Client from an Open API / Swagger specification file </span><br />
<br />
With this tool I can easily switch from NSwag, AutoRest, Swagger Codegen, and OpenAPI Codegen, and re-generate my code by making changes directly to the OpenAPI specification document I have in my project.<br />
<br />
<div class="separator" style="clear: both; text-align: left;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDEdq1vewVvMVPOrUJvpMOpzcpso4O9eXtcbC9KAmL3XObA5m1rglSUdJFWqEzbau-a_eFIq2gxGX83hYZm13BqkbKLxMtRvkKECQlZ5tlqWMZfu3VUwlKrgTZFWe6VqD122vnmFPugB2l/s1600/solution-explorer-context-menu.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="528" data-original-width="706" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDEdq1vewVvMVPOrUJvpMOpzcpso4O9eXtcbC9KAmL3XObA5m1rglSUdJFWqEzbau-a_eFIq2gxGX83hYZm13BqkbKLxMtRvkKECQlZ5tlqWMZfu3VUwlKrgTZFWe6VqD122vnmFPugB2l/s1600/solution-explorer-context-menu.jpg" /></a></div><br />
<br />
I built <a href="https://docs.microsoft.com/en-us/visualstudio/extensibility/internals/custom-tools?view=vs-2019" target="_blank">Visual Studio Custom Tools</a> for each code generator so every time I make changes to the OpenAPI specification document in my project, the client code gets automatically re-generated.<br />
<br />
<div class="separator" style="clear: both; text-align: left;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi0CfLyd-M33RwFbo78TrSqC5DeixEp1XFVJ6TofSIfjIRJ27eIvH7UXJSAPCq64YhxRETVRX0rL8k8BOJf-roFrdPzZ8jjm7_KetOyQgz6a7uZcvrk4QadVNMBlVArYA43vYwnLrbE_3Nw/s1600/autorestcodegenerator-custom-tool.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="475" data-original-width="345" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi0CfLyd-M33RwFbo78TrSqC5DeixEp1XFVJ6TofSIfjIRJ27eIvH7UXJSAPCq64YhxRETVRX0rL8k8BOJf-roFrdPzZ8jjm7_KetOyQgz6a7uZcvrk4QadVNMBlVArYA43vYwnLrbE_3Nw/s1600/autorestcodegenerator-custom-tool.jpg" /></a></div><br />
<div class="separator" style="clear: both; text-align: left;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYWJ1JjjjqXZ9QOqVqCXgQVHngZbDk95TMdlJR_ubj5_R7NRdGL1M387QQXDKqhFMKcaYl2oD8JlpyN4W6mJJRabzRd5yKKPH2ruAnpAaNiv0RvY_u44mSHe9MF9UM60UvRg0E3aN40dXq/s1600/openapicodegenerator-custom-tool.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="514" data-original-width="349" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYWJ1JjjjqXZ9QOqVqCXgQVHngZbDk95TMdlJR_ubj5_R7NRdGL1M387QQXDKqhFMKcaYl2oD8JlpyN4W6mJJRabzRd5yKKPH2ruAnpAaNiv0RvY_u44mSHe9MF9UM60UvRg0E3aN40dXq/s1600/openapicodegenerator-custom-tool.jpg" /></a></div><br />
<div class="separator" style="clear: both; text-align: left;"></div><div class="separator" style="clear: both; text-align: left;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjLvZ7h2PXCnPnzzpNx6gg5X6wazVBZmVGKyliP_2KWKODe8uH1WNLYGbC6hsVuVSbUyvK6OoaJ1fN78l5nWtJSZdDbSsD9WbfJyKJIurBeS2uS7p0EcewZ__c-DWCtyHtOYs39goDoQSWD/s1600/swaggercodegenerator-custom-tool.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="506" data-original-width="346" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjLvZ7h2PXCnPnzzpNx6gg5X6wazVBZmVGKyliP_2KWKODe8uH1WNLYGbC6hsVuVSbUyvK6OoaJ1fN78l5nWtJSZdDbSsD9WbfJyKJIurBeS2uS7p0EcewZ__c-DWCtyHtOYs39goDoQSWD/s1600/swaggercodegenerator-custom-tool.jpg" /></a></div><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; text-align: left;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEghwgZnu3FJqHx0oYR9I3GZ4SLHy2DxpsjwPFZQ4KkwpqTjRmAA2h3qZixDTuIjGc4cP8LL-k3cBwD1G7yg5NomqWLGpKGQlFtiBYjy0cH2tB0VC0LSq8skl-HGHHWjqF3cH-FY6u5f45yw/s1600/nswagcodegenerator-custom-tool.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="486" data-original-width="345" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEghwgZnu3FJqHx0oYR9I3GZ4SLHy2DxpsjwPFZQ4KkwpqTjRmAA2h3qZixDTuIjGc4cP8LL-k3cBwD1G7yg5NomqWLGpKGQlFtiBYjy0cH2tB0VC0LSq8skl-HGHHWjqF3cH-FY6u5f45yw/s1600/nswagcodegenerator-custom-tool.jpg" /></a></div><div class="separator" style="clear: both; text-align: left;"><br />
</div><br />
You can include an <a href="https://github.com/RicoSuter/NSwag/wiki/NSwagStudio" target="_blank">NSwag Studio</a> file in the project and right click and re-generate my client code<br />
<br />
<div class="separator" style="clear: both; text-align: left;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjqBeTu48Cnu2DvVGAOA5GlBulF_2yLQMvqzTWVeHlnP-aGn69xRgLyrW-AVetJ0J_kq9R0Eq5aIaHSQvekWJGbLRMI-jktODaWXzQ6bUMvBfpNDC_kXVsGwNdEknzFaY5FBFH58G8Wd0OR/s1600/nswagstudio-context-menu.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="504" data-original-width="596" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjqBeTu48Cnu2DvVGAOA5GlBulF_2yLQMvqzTWVeHlnP-aGn69xRgLyrW-AVetJ0J_kq9R0Eq5aIaHSQvekWJGbLRMI-jktODaWXzQ6bUMvBfpNDC_kXVsGwNdEknzFaY5FBFH58G8Wd0OR/s1600/nswagstudio-context-menu.jpg" /></a></div><span id="goog_518793397"></span><span id="goog_518793398"></span><br />
And a feature that I just built today, adding a dialog for adding a new OpenAPI specification document file.<br />
<br />
<div class="separator" style="clear: both; text-align: left;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQTupk7zqVbsR9f7rUVABsFvpjo92ea4cYFDxNBmNHgaV4WUJ2bCMQ0q8aCnFwhIecfdir4f19SlRTjRqo4xnWiw3vK_OIqtG5szvzf1pWaqttCM5iw-Uam1cS4g3duOIAPN9wSEAZaXR3/s1600/add-new-menu.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="267" data-original-width="708" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQTupk7zqVbsR9f7rUVABsFvpjo92ea4cYFDxNBmNHgaV4WUJ2bCMQ0q8aCnFwhIecfdir4f19SlRTjRqo4xnWiw3vK_OIqtG5szvzf1pWaqttCM5iw-Uam1cS4g3duOIAPN9wSEAZaXR3/s1600/add-new-menu.png" /></a></div><br />
<div class="separator" style="clear: both; text-align: left;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEitl16vRHRQ-ykbZ2vfexmfoirL9xmQO6fsMSIVmO4n_RBPmTLfIQzA-zNqw6jYPsU4IjFsLmjkKLRTpDG_FY5eyesrAYXCV0gU1tQ_1c6r80aKtODzLa7VxQfO_HXomrnArIg_61wWC5Vx/s1600/add-new-dialog.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="187" data-original-width="551" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEitl16vRHRQ-ykbZ2vfexmfoirL9xmQO6fsMSIVmO4n_RBPmTLfIQzA-zNqw6jYPsU4IjFsLmjkKLRTpDG_FY5eyesrAYXCV0gU1tQ_1c6r80aKtODzLa7VxQfO_HXomrnArIg_61wWC5Vx/s1600/add-new-dialog.png" /></a></div><br />
<br />
<span style="background-color: white; color: #191e23; font-family: "noto serif"; font-size: 16px; white-space: pre-wrap;">This project is open source and you get browse the repository on </span><a href="https://github.com/christianhelle/apiclientcodegen" style="background-color: white; box-sizing: inherit; color: #007fac; font-family: "Noto Serif"; font-size: 16px; outline: 0px; transition-duration: 0.05s; transition-property: border, background, color; transition-timing-function: ease-in-out; white-space: pre-wrap;">here</a><span style="background-color: white; color: #191e23; font-family: "noto serif"; font-size: 16px; white-space: pre-wrap;"> and download the VSIX file from the </span><a href="https://marketplace.visualstudio.com/items?itemName=ChristianResmaHelle.APIClientCodeGenerator" style="background-color: white; box-sizing: inherit; color: #007fac; font-family: "Noto Serif"; font-size: 16px; outline: 0px; transition-duration: 0.05s; transition-property: border, background, color; transition-timing-function: ease-in-out; white-space: pre-wrap;">Visual Studio Marketplace</a><br />
<br />
<br />
Christian Resma Hellehttp://www.blogger.com/profile/16521776612083091477noreply@blogger.com0tag:blogger.com,1999:blog-4995334164049002857.post-16964801649102677992018-06-10T21:42:00.000+02:002018-06-11T15:30:24.359+02:00New Challenges in the CloudI have been building mobile solutions for nearly 2 decades, I have seen things come and go, and I had loads of fun working in this space. A great part of my mobile development career involved consulting and for most of my work, I build the entire solution, including the web services and the data store and I am extremely proud of the things I have built. For the past 4 years I have been working in the Music Streaming industry. Using the tools from Xamarin, we built software for Android and iOS with a very large shared code base. The entire organization shares components through different platforms, it was great. Our products have a very high number of daily active users and has great ratings on the Apple AppStore and Google Play.<br />
<br />
During these 4 years, a lot of things has happened. Microsoft acquired HockeyApp then later on Xamarin a few years back, and unfortunately, things went down hill. This is of course almost to be expected as Microsoft has bigger plans for these products and they will be all well integrated into a larger suite of products. I think things are starting to look better now, but for a very long while, it has been much worse. For instrumentation we had to switch from Xamarin Insights to RayGun. At that time when we did the switch, RayGun didn't have the same feature set as Xamarin Insights so it felt like a down grade, with a higher price tag. RayGun eventually caught up and also improved the pricing plan.<br />
<br />
Like anything else, if you work on the same suite of products for 4 years, no matter how fun it is, it becomes less and less exciting. Lately I have taken a keen interest in the recent developments in the Microsoft Azure space and early this year a very interesting opportunity presented itself. So after weeks of consideration, I decided to take a break from full time mobile development. For the past 2 months I have been a full time Cloud developer. Although I still do side projects and most of them will most likely still be mobile, I will be working on Cloud based solutions in my day job.Christian Hellehttp://www.blogger.com/profile/16523297321435081745noreply@blogger.com0tag:blogger.com,1999:blog-4995334164049002857.post-63036477060949782032016-09-01T00:30:00.000+02:002016-09-02T14:42:24.871+02:00Working with Native Bitmap pixel buffers in Xamarin.FormsI mentioned in my previous post that extracting pixel buffers from native Bitmap API’s can be quite tricky. In this post I would like to share the approach that I took for extracting native Bitmap pixel buffers into an collection of Xamarin.Forms.Colors objects so it can be used from a portable class library. I wrote and used a more complex version of the code mentioned in this post on my last project where I was working with image detection and color analysis for an app using Xamarin.Forms, in this project all my color analysis was done in a Portable Class Library using an abstraction over the native bitmap data.<br />
<br />
<strong>BitmapData abstraction</strong><br />
<br />
In .NET you had access to an API called <a href="http://msdn.microsoft.com/en-us/library/system.drawing.bitmap.aspx" title="System.Drawing.Bitmap" target="_blank" data-saferedirecturl="https://www.google.com/url?hl=en&q=http://msdn.microsoft.com/en-us/library/system.drawing.bitmap.aspx&source=gmail&ust=1472906022125000&usg=AFQjCNFdTAWv23M6PLDEmy5WxYn8Tk8gaA">System.Drawing.Bitmap</a> which encapsulates a low-level Windows API called Bitmap from GDI. The managed Bitmap class exposed a method called <a href="https://msdn.microsoft.com/en-us/library/5ey6h79d.aspx" title="LockBits" target="_blank" data-saferedirecturl="https://www.google.com/url?hl=en&q=https://msdn.microsoft.com/en-us/library/5ey6h79d.aspx&source=gmail&ust=1472906022125000&usg=AFQjCNEyw2uJprx7N_vlxVCvmjEIHcONSQ">LockBits</a> which in return gave you a <a href="https://msdn.microsoft.com/en-us/library/5ey6h79d.aspx" title="BitmapData" target="_blank" data-saferedirecturl="https://www.google.com/url?hl=en&q=https://msdn.microsoft.com/en-us/library/5ey6h79d.aspx&source=gmail&ust=1472906022125000&usg=AFQjCNEyw2uJprx7N_vlxVCvmjEIHcONSQ">BitmapData</a> instance. BitmapData exposed information that allows you to manipulate the pixel buffer at a pointer level and is the fastest and recommended way to analyze and manipulate pixel information. I loved the BitmapData class but my portable class library implementation will not contain anything but a pixel buffer in ARGB and a Get/SetPixel(x,y, Color) method and a method for getting the average color of a certain area in the Bitmap to demonstrate what this can be used for<br />
<br />
Here's the code<br />
<br />
<div style="background:#ffffff;border-width:0.1em 0.1em 0.1em 0.8em;border:none;overflow:auto;padding:0.2em 0.6em;width:auto"><pre style="line-height:125%;margin:0"><span style="color:blue">public</span> <span style="color:blue">class</span> <span style="color:#2b91af">BitmapData</span>
{
<span style="color:blue">public</span> BitmapData(Size size, <span style="color:#2b91af">int</span>[] pixelBuffer)
{
Size = size;
PixelBuffer = pixelBuffer;
}
<span style="color:blue">public</span> <span style="color:#2b91af">int</span>[] PixelBuffer { <span style="color:blue">get</span>; }
<span style="color:blue">public</span> Size Size { <span style="color:blue">get</span>; }
<span style="color:blue">public</span> Color GetPixel(Point point) => GetPixel(point.X, point.Y);
<span style="color:blue">public</span> Color GetPixel(<span style="color:#2b91af">double</span> x, <span style="color:#2b91af">double</span> y) => Color.FromUint((<span style="color:#2b91af">uint</span>)<wbr>PixelBuffer[(<span style="color:#2b91af">int</span>)x * (<span style="color:#2b91af">int</span>)y]);
<span style="color:blue">public</span> <span style="color:blue">void</span> SetPixel(Point point, Color color) => SetPixel((<span style="color:#2b91af">int</span>)point.X, (<span style="color:#2b91af">int</span>)point.Y, color);
<span style="color:blue">public</span> <span style="color:blue">void</span> SetPixel(<span style="color:#2b91af">double</span> x, <span style="color:#2b91af">double</span> y, Color color) => PixelBuffer[(<span style="color:#2b91af">int</span>)(x * y)] = (<span style="color:#2b91af">int</span>)(color.A * <span style="color:#2b91af">byte</span>.MaxValue) << 24 |
((<span style="color:#2b91af">int</span>)color.R * <span style="color:#2b91af">byte</span>.MaxValue) << 16 |
((<span style="color:#2b91af">int</span>)color.G * <span style="color:#2b91af">byte</span>.MaxValue) << 8 |
((<span style="color:#2b91af">int</span>)color.B * <span style="color:#2b91af">byte</span>.MaxValue) << 0;
<span style="color:blue">public</span> Color GetAverageColor(<span style="color:blue">params</span> Rectangle[] rectangles)
{
<span style="color:#2b91af">var</span> colors = <span style="color:blue">new</span> List<Color>();
<span style="color:blue">foreach</span> (<span style="color:#2b91af">var</span> rectangle <span style="color:blue">in</span> rectangles)
<span style="color:blue">for</span> (<span style="color:#2b91af">var</span> y = rectangle.Y; y < rectangle.Y + rectangle.Height; y++)
<span style="color:blue">for</span> (<span style="color:#2b91af">var</span> x = (<span style="color:#2b91af">int</span>)rectangle.X; x < (<span style="color:#2b91af">int</span>)rectangle.X + (<span style="color:#2b91af">int</span>)rectangle.Width; x++)
colors.Add(GetPixel(x, y));
<span style="color:#2b91af">var</span> red = (<span style="color:#2b91af">int</span>)(colors.Average(c => c.R) * <span style="color:#2b91af">byte</span>.MaxValue);
<span style="color:#2b91af">var</span> blue = (<span style="color:#2b91af">int</span>)(colors.Average(c => c.G) * <span style="color:#2b91af">byte</span>.MaxValue);
<span style="color:#2b91af">var</span> green = (<span style="color:#2b91af">int</span>)(colors.Average(c => c.B) * <span style="color:#2b91af">byte</span>.MaxValue);
<span style="color:#2b91af">var</span> alpha = (<span style="color:#2b91af">int</span>)(colors.Average(c => c.A) * <span style="color:#2b91af">byte</span>.MaxValue);
<span style="color:blue">return</span> Color.FromRgba(red, blue, green, alpha);
}
}
</pre></div><br />
<strong>UIImage to BitmapData (iOS)</strong><br />
<br />
To get the pixel buffer from a <a href="https://developer.xamarin.com/api/type/MonoTouch.UIKit.UIImage/" target="_blank" data-saferedirecturl="https://www.google.com/url?hl=en&q=https://developer.xamarin.com/api/type/MonoTouch.UIKit.UIImage/&source=gmail&ust=1472906022125000&usg=AFQjCNGrFpwsmNbpo7IM_h-Jt6vEGNEIVQ">UIImage</a> instance we need to draw it to a new drawing surface by calling <a href="https://developer.xamarin.com/api/member/CoreGraphics.CGContext.DrawImage/p/CoreGraphics.CGImage/CoreGraphics.CGRect/" target="_blank" data-saferedirecturl="https://www.google.com/url?hl=en&q=https://developer.xamarin.com/api/member/CoreGraphics.CGContext.DrawImage/p/CoreGraphics.CGImage/CoreGraphics.CGRect/&source=gmail&ust=1472906022125000&usg=AFQjCNHJ-sXbKia_LK-Li8IHXZ7SO5kpow">DrawImage</a> on an <a href="https://developer.xamarin.com/api/type/CoreGraphics.CGBitmapContext/" target="_blank" data-saferedirecturl="https://www.google.com/url?hl=en&q=https://developer.xamarin.com/api/type/CoreGraphics.CGBitmapContext/&source=gmail&ust=1472906022125000&usg=AFQjCNGjrOomItPXs-bHn3X5gYiz_MBAAQ">CGBitmapContext</a> instance. When we construct the drawing surface we specify the pixel format and provide a pointer or an array of bytes in which the data will be written to. We need to specify that the pixels will contain a byte for each component, 4 bytes per pixel, and that the byte order is 32-bit Big Endian. We can also specify whether we specify the alpha component is in the most or least significant bits of each pixel, but for this example I will put it in the end since when I was researching about this, most of the examples I found used the least significant bit to store the alpha component.<br />
<br />
Here's the code<br />
<br />
<div style="background:#ffffff;border-width:0.1em 0.1em 0.1em 0.8em;border:none;overflow:auto;padding:0.2em 0.6em;width:auto"><pre style="line-height:125%;margin:0"><span style="color:blue">public</span> BitmapData Convert(<span style="color:#2b91af">object</span> nativeBitmap)
{
<span style="color:#2b91af">var</span> image = (UIImage)nativeBitmap;
<span style="color:blue">return</span> <span style="color:blue">new</span> BitmapData(<span style="color:blue">new</span> Xamarin.Forms.Size(image.Size.<wbr>Width, image.Size.Height), GetPixels(image));
}
<span style="color:blue">private</span> <span style="color:blue">static</span> <span style="color:#2b91af">int</span>[] GetPixels(UIImage image)
{
<span style="color:blue">const</span> <span style="color:#2b91af">int</span> bytesPerPixel = 4;
<span style="color:blue">const</span> <span style="color:#2b91af">int</span> bitsPerComponent = 8;
<span style="color:blue">const</span> CGBitmapFlags flags = CGBitmapFlags.ByteOrder32Big | CGBitmapFlags.<wbr>PremultipliedLast;
<span style="color:#2b91af">var</span> width = (<span style="color:#2b91af">int</span>)image.CGImage.Width;
<span style="color:#2b91af">var</span> height = (<span style="color:#2b91af">int</span>)image.CGImage.Height;
<span style="color:#2b91af">var</span> bytesPerRow = bytesPerPixel * width;
<span style="color:#2b91af">var</span> buffer = <span style="color:blue">new</span> <span style="color:#2b91af">byte</span>[bytesPerRow * height];
<span style="color:#2b91af">var</span> pixels = <span style="color:blue">new</span> <span style="color:#2b91af">int</span>[width * height];
<span style="color:#2b91af">var</span> handle = GCHandle.Alloc(buffer);
<span style="color:blue">try</span>
{
<span style="color:blue">using</span> (<span style="color:#2b91af">var</span> colorSpace = CGColorSpace.CreateGenericRgb(<wbr>))
<span style="color:blue">using</span> (<span style="color:#2b91af">var</span> context = <span style="color:blue">new</span> CGBitmapContext(buffer, width, height, bitsPerComponent, bytesPerRow, colorSpace, flags))
context.DrawImage(<span style="color:blue">new</span> RectangleF(0, 0, width, height), image.CGImage);
<span style="color:blue">for</span> (<span style="color:#2b91af">var</span> y = 0; y < height; y++)
{
<span style="color:#2b91af">var</span> offset = y * width;
<span style="color:blue">for</span> (<span style="color:#2b91af">var</span> x = 0; x < width; x++)
{
<span style="color:#2b91af">var</span> idx = bytesPerPixel * (offset + x);
<span style="color:#2b91af">var</span> r = buffer[idx + 0];
<span style="color:#2b91af">var</span> g = buffer[idx + 1];
<span style="color:#2b91af">var</span> b = buffer[idx + 2];
<span style="color:#2b91af">var</span> a = buffer[idx + 3];
pixels[x * y] = a << 24 | r << 16 | g << 8 | b << 0;
}
}
}
<span style="color:blue">finally</span>
{
handle.Free();
}
<span style="color:blue">return</span> pixels;
}
</pre></div><br />
<strong>Bitmap to BitmapData (Android)</strong><br />
<br />
This is pretty easy to do in Android as the <a href="https://developer.xamarin.com/api/type/Android.Graphics.Bitmap/" target="_blank" data-saferedirecturl="https://www.google.com/url?hl=en&q=https://developer.xamarin.com/api/type/Android.Graphics.Bitmap/&source=gmail&ust=1472906022125000&usg=AFQjCNFefaS6uVP7Oj7NxVVMGU2kW4uBaA">Bitmap</a> class exposes the <a href="https://developer.xamarin.com/api/member/Android.Graphics.Bitmap.GetPixels/p/System.Int32%5B%5D/System.Int32/System.Int32/System.Int32/System.Int32/System.Int32/System.Int32/" target="_blank" data-saferedirecturl="https://www.google.com/url?hl=en&q=https://developer.xamarin.com/api/member/Android.Graphics.Bitmap.GetPixels/p/System.Int32%255B%255D/System.Int32/System.Int32/System.Int32/System.Int32/System.Int32/System.Int32/&source=gmail&ust=1472906022125000&usg=AFQjCNGQHYvaSTufIWvi3dtiQEiYtmexxQ">GetPixels</a> method to get the pixel buffer and the pixel information is conveniently stored in ARGB<br />
<br />
Here's the code<br />
<br />
<div style="background:#ffffff;border-width:0.1em 0.1em 0.1em 0.8em;border:none;overflow:auto;padding:0.2em 0.6em;width:auto"><pre style="line-height:125%;margin:0"><span style="color:blue">public</span> BitmapData Convert(<span style="color:#2b91af">object</span> nativeBitmap)
{
<span style="color:#2b91af">var</span> bitmap = (Bitmap)nativeBitmap;
<span style="color:#2b91af">var</span> info = bitmap.GetBitmapInfo();
<span style="color:#2b91af">var</span> pixels = <span style="color:blue">new</span> <span style="color:#2b91af">int</span>[info.Width * info.Height];
bitmap.GetPixels(pixels, 0, (<span style="color:#2b91af">int</span>)info.Width, 0, 0, (<span style="color:#2b91af">int</span>)info.Width, (<span style="color:#2b91af">int</span>)info.Height);
<span style="color:blue">return</span> <span style="color:blue">new</span> BitmapData(<span style="color:blue">new</span> Xamarin.Forms.Size(info.Width, info.Height), pixels);
}
</pre></div><br />
<strong>WriteableBitmap to BitmapData (Universal Windows Platform)</strong><br />
<br />
To do this using the Universal Windows Platform is a bit similar to iOS but is less complex. The <a href="https://msdn.microsoft.com/library/windows/apps/xaml/windows.ui.xaml.media.imaging.writeablebitmap.aspx" target="_blank" data-saferedirecturl="https://www.google.com/url?hl=en&q=https://msdn.microsoft.com/library/windows/apps/xaml/windows.ui.xaml.media.imaging.writeablebitmap.aspx&source=gmail&ust=1472906022125000&usg=AFQjCNHzlIhwdKujbkpdPy3972Dp5WHx7w">WriteableBitmap</a> class exposes a <a href="https://msdn.microsoft.com/en-us/library/windows/apps/xaml/windows.ui.xaml.media.imaging.writeablebitmap.pixelbuffer.aspx" target="_blank" data-saferedirecturl="https://www.google.com/url?hl=en&q=https://msdn.microsoft.com/en-us/library/windows/apps/xaml/windows.ui.xaml.media.imaging.writeablebitmap.pixelbuffer.aspx&source=gmail&ust=1472906022125000&usg=AFQjCNFGv4F_f86UzCU1jMK-isldk756tg">PixelBuffer </a>as an <a href="https://msdn.microsoft.com/en-us/library/windows/apps/xaml/windows.storage.streams.ibuffer.aspx" target="_blank" data-saferedirecturl="https://www.google.com/url?hl=en&q=https://msdn.microsoft.com/en-us/library/windows/apps/xaml/windows.storage.streams.ibuffer.aspx&source=gmail&ust=1472906022126000&usg=AFQjCNFOsDPOQkjuu1EIOKXJ6NO4XfTMVQ">IBuffer </a>in which you can call the extension method ToArray() on to get an array of integers. The interesting part about the WriteableBitmap PixelBuffer is that it doesn't really say anywhere in the documentation (at least not directly) that the component order is BGRA, I only figured this out by reading the sample code provided in the <a href="https://msdn.microsoft.com/library/windows/apps/xaml/windows.ui.xaml.media.imaging.writeablebitmap.aspx" target="_blank" data-saferedirecturl="https://www.google.com/url?hl=en&q=https://msdn.microsoft.com/library/windows/apps/xaml/windows.ui.xaml.media.imaging.writeablebitmap.aspx&source=gmail&ust=1472906022126000&usg=AFQjCNFBFyioaJ4Wv8NPk3CheFjBR3eKgw">WriteableBitmap</a> <wbr>documentation where it says in a code comment that <b>WriteableBitmap uses BGRA format</b>.<br />
<br />
Here's the code<br />
<br />
<div style="background:#ffffff;border-width:0.1em 0.1em 0.1em 0.8em;border:none;overflow:auto;padding:0.2em 0.6em;width:auto"><pre style="line-height:125%;margin:0"><span style="color:blue">public</span> BitmapData Convert(<span style="color:#2b91af">object</span> nativeBitmap)
{
<span style="color:#2b91af">var</span> imageSource = (WriteableBitmap)nativeBitmap;
<span style="color:#2b91af">var</span> pixelData = GetPixelDataFromImage(<wbr>imageSource).ToArray();
<span style="color:blue">return</span> <span style="color:blue">new</span> BitmapData(<span style="color:blue">new</span> Size(imageSource.PixelWidth, imageSource.PixelHeight), pixelData);
}
<span style="color:blue">private</span> <span style="color:blue">static</span> IEnumerable<<span style="color:#2b91af">int</span>> GetPixelDataFromImage(<wbr>WriteableBitmap imageSource)
{
<span style="color:blue">const</span> <span style="color:#2b91af">int</span> bytesPerPixel = 4;
<span style="color:#2b91af">var</span> pixelHeight = imageSource.PixelHeight;
<span style="color:#2b91af">var</span> pixelWidth = imageSource.PixelWidth;
<span style="color:#2b91af">var</span> buffer = imageSource.PixelBuffer.<wbr>ToArray();
<span style="color:#2b91af">var</span> pixels = <span style="color:blue">new</span> <span style="color:#2b91af">int</span>[buffer.Length];
<span style="color:blue">for</span> (<span style="color:#2b91af">var</span> y = 0; y < pixelHeight; y++)
{
<span style="color:#2b91af">var</span> offset = y * pixelWidth;
<span style="color:blue">for</span> (<span style="color:#2b91af">var</span> x = 0; x < pixelWidth; x++)
{
<span style="color:#2b91af">var</span> idx = bytesPerPixel * (offset + x);
<span style="color:#2b91af">var</span> b = buffer[idx + 0];
<span style="color:#2b91af">var</span> g = buffer[idx + 1];
<span style="color:#2b91af">var</span> r = buffer[idx + 2];
<span style="color:#2b91af">var</span> a = buffer[idx + 3];
pixels[x * y] = a << 24 | r << 16 | g << 8 | b << 0;
}
}
<span style="color:blue">return</span> pixels;
}
</pre></div><br />
I remember struggling quite a bit when I was figuring out what I just shared and I hope that some one out there might be able to make some good use of it.<br />
Christian Resma Hellehttp://www.blogger.com/profile/16521776612083091477noreply@blogger.com1tag:blogger.com,1999:blog-4995334164049002857.post-56852664822310868102016-08-31T23:35:00.001+02:002016-08-31T23:35:50.448+02:00Over 2 years of Xamarin<p dir="ltr">I have held radio silence for over 2 years because I am having a blast doing nothing but Xamarin based development. During this time I have been fully involved in building music apps that I actually use in my everyday life. I struggled with the pains and gained a love/hate relationship with the development tools I use. I work primarily on a Mac since the products we build only target iOS and Android and I adore Xamarin Studio, it’s super fast and simple and it reminds me of the good old bad days of Visual Studio from over a decade ago where it was pretty much just a big text editor with a few fancy features. Xamarin Studio of course has its ups and downs and sometimes it just doesn’t want to cooperate. Every time a new “stable” version is out I needed to make sure that I only update during non-busy days as I risk losing all productivity if I install an update with breaking changes, or an update that is just simply broken. Some updates do break stuff! Some breaking changes are minor and easy to fix and some are rather complex to work around the problem. I remember once, our builds broke because the command line build tooling somehow got deprecated suggesting us to move from MDTool to XBuild, although the change sounds trivial it costed me a full day of work to update all our build scripts and double check every single build configuration that they work as they should in our build servers</p><p dir="ltr">On top of having a full time position doing Xamarin development for a Music Services company, I also do a few side project. For these projects I use Xamarin.Forms as it shows a lot of promise. The early versions were terrible but they eventually got much better. For simple UI requirements its absolutely perfect. With Xamarin.Forms you can create a cross platform UI that you only write once using either a flavor of XAML or in code (using C# in my case). In Xamarin.Forms you can either take advantage of the sharable UI tooling so you only have to write the UI code once and have it rendered natively on iOS, Android, and Windows Phone, or you can create custom renderers that allow you fully control using the API’s of the platforms you target to implement the control or the entire screen. When you end up implementing the entire app using custom renderers then Xamarin.Forms starts making less sense for what you’re trying to build, but for Line-of-Business apps its perfect. I can really see a big future in Xamarin.Forms</p><p dir="ltr">Knowing and understanding the platform is always better than relying on cross platform tools. I have mostly been working on multi-platform solutions throughout my career and the experience I gained has been a great advantage for me as I understand how a lot of things work and why API’s do what they do. A good example of such cross platform issues is working with Bitmaps. In a nutshell, a bitmap is an array of 32-bit integers containing the Red-Blue-Green-Alpha pixel information. If you do cross platform development and image processing you will need to ensure that the order of the pixel information bytes are uniform so that the algorithm you work with will work across all the targetted platforms. This might come as a surprise to some but pixel information is stored differently for every platform’s Bitmap API, for example, iOS uses Red-Blue-Green-Alpha, Android uses Alpha-Red-Blue-Green, and Windows uses Blue-Green-Red-Alpha. All these platforms have API’s that allow you retrieve the pixel buffer (the array of 32-bit integers) in a single call avoiding calling using slow API’s like GetPixel(x,y) hundreds or even thousands of times. Too make things even more fun the <strong>Xamarin.Forms.Color </strong>structure has a static helper method called <strong>FromUint(uint argb)</strong> but the documentation (at the current time of writing) describes the method as <strong>Returns a new Color with the requested RGBA value</strong> and the method parameter is described as <strong>A uint that represents the ARGB value of the color </strong>and the return value is described as <strong>An RGBA color</strong>. So that was a bit confusing! Eventually Xamarin will correct these small details or developers will just have to live with them</p><p dir="ltr">I just ended a side project and will probably not take on any new side projects for a while so I can spend more time learning new awesome stuff, or in some case understanding old awesome stuff. I have a few hobby projects that I have been intending to open source for a while so I’ll probably finish those up and finally publish them. I had some a bit success with some open source projects such as SQL Compact Query Analyzer (50k downloads), SQL Compact Code Generator (15k downloads), and ResW File Code Generator (4k downloads), all which had very constructive and positive reviews. I always enjoyed building developer tools and I hope to get more of that done in the nearest future</p>Christian Resma Hellehttp://www.blogger.com/profile/16521776612083091477noreply@blogger.comtag:blogger.com,1999:blog-4995334164049002857.post-1673581658686054252014-05-02T00:19:00.001+02:002018-06-10T20:59:19.816+02:00My future is XamarinI have been creating software for handheld devices for over a decade now. I’ve seen interesting things come and go and also witnessed a couple of failures. A great part of my mobile development career involved consulting and I had loads of fun working with some very smart people doing all sorts of interesting stuff. But for the past year or so I felt like I fell into a deep whole. Normally I would provide consulting services for up to 6 months then move on to something else, but my last project was not the case. It was retailer solution and was not really interesting, not at all challenging, and was mostly tedious, and to make it worse I was targeting a 10 year old platform and needed to support an even older one. I first went along with this because the company was going through a hard time and could really use some revenue, at that time we had just let go of 1/3 of our staff and I felt lucky that I got to keep my job. I did my job the best I could even and delivered what needed to be shipped. As the project progressed and the requirement changes got out of hand I found myself in an endless loop of fixing then breaking then fixing stuff. Sometimes in life you just have to suck it up and do your job since after all it pays the bills, keeps a roof over our heads, and puts food on the table. This project has taken all of my time and energy. It was the main reason I have not posted a single article for an entire year!<br />
<br />
During this time I paid a lot of attention (more than usual) to what was going on in the mobile space and I have grown an interest in Xamarin. I’ve seen more and more people adapt Xamarin and after trying it in a few small projects I could really see why. This means a lot coming from me since I am a huge fan of native platform development. I’ve done Android projects before where I used Java + Eclipse and iOS projects where I used Objective-C + XCode. But after seeing and trying out Xamarin, thanks to my experience with Android and iOS, I found myself immediately being productive. I love the fact that I can just use the official Android or iOS documentation pages and be able to implement it directly using Xamarin. <br />
So after months of considerations I have decided to take a break from consulting and take on a full time position for a company called <a href="http://www.247entertainment.com/">24/7 Entertainment</a> where I will be doing Xamarin development. I have worked with the company in the past where I helped them with some Windows Phone and Store music apps. I know the team from past work experiences and I know that they are loads of fun to work with and are very passionate about what they do. They believe in their products and all share common goals. They follow modern software development practices and use the latest and the greatest development tools and hardware. This job is going to be fun, challenging, and simply great! I hope to learn, contribute, and have a blast!Christian Resma Hellehttp://www.blogger.com/profile/16521776612083091477noreply@blogger.com2tag:blogger.com,1999:blog-4995334164049002857.post-51937645921109988602013-05-05T23:31:00.000+02:002013-05-06T17:02:52.269+02:00Integrating with the Windows Phone 8 Lock ScreenA nice new feature in Windows Phone 8 is integration with the lock screen. As a developer, you can now display notification icons the same way the Outlook app displays New Mail notifications. You can also change the background image of the lock screen from your app. The information used for displaying notification is the exact same information that an app uses to display notifications on the app’s primary tile regardless if the app is pinned to the start screen or not <br />
<br />
<strong>Notification Icon</strong><br />
<br />
To display an icon on the lock screen you must follow a small set of strict rules on how your image file should be. The image has to be a<strong> 38 x 38 PNG image that contains only white pixels and some levels of transparency</strong>. Yes, I know it’s a bit strict but it makes sense as the icon notifications are designed to be very discreet. <br />
<strong><br /></strong>
<strong>App Manifest</strong><br />
<br />
You need to define a few extensions to let the operating system allow your app to integrate with the lock screen. So here’s what we need to do, open the WMAppManifest.xml file using an XML editor, to do this right click on the WMAppManifest.xml file and select <strong>Open With</strong>, and use the <strong>XML (Text) Editor</strong>. First, we need to define the <strong><DeviceLockImageURI></strong> element in the primary token. The DeviceLockImageURI describes which image file to display in the lock screen as an icon. To define DeviceLockImageURI, insert the following element in the <strong><PrimaryToken></strong> <br />
<blockquote>
<pre style="background: white; color: black; font-family: consolas; font-size: 13px;"><span style="color: blue;"><</span><span style="color: #a31515;">DeviceLockImageURI</span><span style="color: blue;"> </span><span style="color: red;">IsRelative</span><span style="color: blue;">=</span>"<span style="color: blue;">true</span>"
<span style="color: blue;"> </span><span style="color: red;">IsResource</span><span style="color: blue;">=</span>"<span style="color: blue;">false</span>"<span style="color: blue;">></span>Assets\YourLockImage.png<span style="color: blue;"></</span><span style="color: #a31515;">DeviceLockImageURI</span><span style="color: blue;">></span></pre>
</blockquote>
Then, insert the following lines after the between the <strong><Tokens></strong> and <strong><ScreenResolutions></strong> definitions<br />
<blockquote>
<pre style="background: white; color: black; font-family: consolas; font-size: 13px;"><span style="color: blue;"><</span><span style="color: #a31515;">Extensions</span><span style="color: blue;">></span>
<span style="color: blue;"> <</span><span style="color: #a31515;">Extension</span><span style="color: blue;"> </span><span style="color: red;">ExtensionName</span><span style="color: blue;">=</span>"<span style="color: blue;">LockScreen_Notification_IconCount</span>"
<span style="color: blue;"> </span><span style="color: red;">ConsumerID</span><span style="color: blue;">=</span>"<span style="color: blue;">{111DFF24-AA15-4A96-8006-2BFF8122084F}</span>"
<span style="color: blue;"> </span><span style="color: red;">TaskID</span><span style="color: blue;">=</span>"<span style="color: blue;">_default</span>"<span style="color: blue;"> /></span>
<span style="color: blue;"> <</span><span style="color: #a31515;">Extension</span><span style="color: blue;"> </span><span style="color: red;">ExtensionName</span><span style="color: blue;">=</span>"<span style="color: blue;">LockScreen_Notification_TextField</span>"
<span style="color: blue;"> </span><span style="color: red;">ConsumerID</span><span style="color: blue;">=</span>"<span style="color: blue;">{111DFF24-AA15-4A96-8006-2BFF8122084F}</span>"
<span style="color: blue;"> </span><span style="color: red;">TaskID</span><span style="color: blue;">=</span>"<span style="color: blue;">_default</span>"<span style="color: blue;"> /></span>
<span style="color: blue;"> <</span><span style="color: #a31515;">Extension</span><span style="color: blue;"> </span><span style="color: red;">ExtensionName</span><span style="color: blue;">=</span>"<span style="color: blue;">LockScreen_Background</span>"
<span style="color: blue;"> </span><span style="color: red;">ConsumerID</span><span style="color: blue;">=</span>"<span style="color: blue;">{111DFF24-AA15-4A96-8006-2BFF8122084F}</span>"
<span style="color: blue;"> </span><span style="color: red;">TaskID</span><span style="color: blue;">=</span>"<span style="color: blue;">_default</span>"<span style="color: blue;"> /></span>
<span style="color: blue;"></</span><span style="color: #a31515;">Extensions</span><span style="color: blue;">></span></pre>
<br /></blockquote>
<strong>Lock screen settings</strong><br />
<br />
Before our app can display notifications we need to configure our Lock Screen settings to allow the type of notification that we are interested in displaying. Currently an app can display 3 types of notifications: background image; detailed status; and quick status. Detailed status is similar to the textual calendar notifications that are displayed using the Outlook Calendar app. Quick status is similar to the way the Outlook Mail app displays notifications, an icon and a count indicator.<br />
<br />
To configure the device to display notifications from your app, go to the settings app and select Lock screen <br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcI1xd5WvrM_KoweuQllS__7xMLMDdrb2hMKJpgeaQNndVXSsWtQ34TPIOoHWFyR9DSkrE2kFbOIvhkFgDDNBStoVwtnTcI91m8z6KMWDhTSnX6Ap3-XITVguUoCoLL_E3CmdnnVoZj4rz/s1600-h/settings%25255B3%25255D.png"><img alt="settings" border="0" height="804" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiagLErXseET6jgNZLThrK_ptn8dGp7BbxlYUp769LLyp9tJQmG9WduAUUwYcOUPUPoycyy9rSVNNkdV3mpR9BlWqrDm2ptObdO_I30ARK_yx_3D5y449hs9kHVpNbqXSXwVcGw7mwsr7Fe/?imgmax=800" style="border-bottom-width: 0px; border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; display: inline;" title="settings" width="484" /></a> <br />
<br />
In the lock screen settings, choose the notification type that will display notifications from our app<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgpzemXFVw7akppRp7vaG2KHPCu8oXmnVf_VxRrebGG40PtSvY5KZRKjHjQYDSRH1Q68SFdFxcC1A5FEid9Ok9BaeP3uGaF2CLx_JdgloEIwx-67LTFyr3_od3LFwW6YUWTxZh1ALew54gn/s1600-h/image%25255B12%25255D.png"><img alt="image" border="0" height="804" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEifZ2s2GVd_eOCenHbIU_aDTndIbcs4UYJs14GvklyLMvR6PVG1kcjyg_5JD5ia1ef8RT9U_Wl5xQYVgg4c1S7iqnvLBkWjnDF4bO6AWMm_D9iLcYxr3RhqO8lg_WmIdYjZckSUXWRw-oDZ/?imgmax=800" style="border-bottom-width: 0px; border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; display: inline;" title="image" width="484" /></a><br />
<br />
For this example we’ll show a quick status notification<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUj_cw57ygn_GBgoJp8lFiTWW7REWfTq60RxXfCgFr1D3KIuiXZQ7_GbBb250GBiAqk9tAB9yQ6kpx-9_7JfYH3foS-0hf3KTb_BI5cjeOct8mjrbP052AssXmB76uY-QnGwdCucU13aX1/s1600-h/quick%252520status%252520on%25255B5%25255D.png"><img alt="quick status on" border="0" height="804" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiW9dxiVUQC0GE6pi_bp2ygNr4akcyoHIi389Lc-s_3lDnQTM9I6pg4k7_LzAk21_93MUbdn-iCjaejgKhnvF1LhEC7w2MSMExaBNF0P86ASMlRcq3Fi78kvQgq-l6_3QR5tprqZT-sxodN/?imgmax=800" style="border-bottom-width: 0px; border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; display: inline;" title="quick status on" width="484" /></a><br />
<br />
<strong>Code</strong><br />
<br />
To update the background image of the lock screen we need use the <a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/windows.phone.system.userprofile.lockscreen(v=vs.105).aspx">LockScreen</a> class of the <a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj207562(v=vs.105).aspx">UserProfile</a> API. First we check if the user configured the app to be able to set the background of the lock screen, we can do this through <a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/windows.phone.system.userprofile.lockscreenmanager(v=vs.105).aspx">LockScreenManager</a> class. If the app isn’t allowed to change the lock screen background then we can open the lock screen settings page.<br />
<div class="wlWriterEditableSmartContent" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:c861d3b8-ab99-412c-a2dc-ec68782562dd" style="display: inline; float: none; margin: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;">
<br />
<div style="border: #000080 1px solid; color: black; font-family: 'Courier New', Courier, Monospace; font-size: 10pt;">
<div style="background: #000080; color: white; font-family: Verdana, Tahoma, Arial, sans-serif; font-weight: bold; padding: 2px 5px;">
Lock screen background (C#)</div>
<br />
<div style="background-color: white; overflow: auto; padding: 2px 5px; white-space: nowrap;">
<span style="background: #ffffff; color: blue;">if</span><span style="background: #ffffff; color: black;"> (</span><span style="background: #ffffff; color: blue;">await</span><span style="background: #ffffff; color: black;"> </span><span style="background: #ffffff; color: #2b91af;">LockScreenManager</span><span style="background: #ffffff; color: black;">.RequestAccessAsync() == </span><span style="background: #ffffff; color: #2b91af;">LockScreenRequestResult</span><span style="background: #ffffff; color: black;">.Granted)</span><br />
<span style="font-size: 10pt;">{</span><br />
<span style="color: black; font-size: 10pt;"> </span><span style="color: blue; font-size: 10pt;">var</span><span style="color: black; font-size: 10pt;"> uri = </span><span style="color: blue; font-size: 10pt;">new</span><span style="color: black; font-size: 10pt;"> </span><span style="color: #2b91af; font-size: 10pt;">Uri</span><span style="color: black; font-size: 10pt;">(</span><span style="color: #a31515; font-size: 10pt;">"ms-appx:///Assets/LockScreenImage.png"</span><span style="color: black; font-size: 10pt;">, </span><span style="color: #2b91af; font-size: 10pt;">UriKind</span><span style="color: black; font-size: 10pt;">.Absolute);</span><br />
<span style="color: black; font-size: 10pt;"> </span><span style="color: #2b91af; font-size: 10pt;">LockScreen</span><span style="color: black; font-size: 10pt;">.SetImageUri(uri);</span><br />
<span style="font-size: 10pt;">}</span><br />
<span style="color: blue; font-size: 10pt;">else</span><br />
<span style="font-size: 10pt;">{</span><br />
<span style="color: black; font-size: 10pt;"> </span><span style="color: green; font-size: 10pt;">// Open the Settings -> Lock Screen settings</span><br />
<span style="color: black; font-size: 10pt;"> </span><span style="color: blue; font-size: 10pt;">await</span><span style="color: black; font-size: 10pt;"> </span><span style="color: #2b91af; font-size: 10pt;">Launcher</span><span style="color: black; font-size: 10pt;">.LaunchUriAsync(</span><span style="color: blue; font-size: 10pt;">new</span><span style="color: black; font-size: 10pt;"> </span><span style="color: #2b91af; font-size: 10pt;">Uri</span><span style="color: black; font-size: 10pt;">(</span><span style="color: #a31515; font-size: 10pt;">"ms-settings-lock:"</span><span style="color: black; font-size: 10pt;">));</span><br />
<span style="font-size: 10pt;">}</span></div>
<br /></div>
<br /></div>
To display an icon notification just update the primary application tile with a notification. We can do this by using the <a href="http://msdn.microsoft.com/en-US/library/windowsphone/develop/microsoft.phone.shell.shelltile(v=vs.105).aspx">ShellTile</a> API<br />
<br />
<div class="wlWriterEditableSmartContent" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:50f569cd-6a48-4f82-a5d5-64596ddca759" style="display: inline; float: none; margin: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;">
<div style="border: #000080 1px solid; color: black; font-family: 'Courier New', Courier, Monospace; font-size: 10pt;">
<div style="background: #000080; color: white; font-family: Verdana, Tahoma, Arial, sans-serif; font-weight: bold; padding: 2px 5px;">
Display notification (C#)</div>
<div style="background-color: white; overflow: auto; padding: 2px 5px; white-space: nowrap;">
<span style="background: #ffffff; color: blue;"><br /></span>
<span style="background: #ffffff; color: blue;">var</span><span style="background: #ffffff; color: black;"> tile = </span><span style="background: #ffffff; color: #2b91af;">ShellTile</span><span style="background: #ffffff; color: black;">.ActiveTiles.First();</span><br />
<span style="color: blue; font-size: 10pt;">var</span><span style="color: black; font-size: 10pt;"> data = </span><span style="color: blue; font-size: 10pt;">new</span><span style="color: black; font-size: 10pt;"> </span><span style="color: #2b91af; font-size: 10pt;">FlipTileData</span><br />
<span style="font-size: 10pt;"> {</span><br />
<span style="font-size: 10pt;"> Count = 1,</span><br />
<span style="color: black; font-size: 10pt;"> Title = </span><span style="color: #a31515; font-size: 10pt;">"Lock Screen Demo"</span><br />
<span style="font-size: 10pt;"> };</span><br />
<span style="font-size: 10pt;">tile.Update(data);</span></div>
<br /></div>
<br /></div>
To clear the notification just update the primary application tile to its original state <br />
<br />
<div class="wlWriterEditableSmartContent" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:c7c41e76-6182-40b7-abd1-3927ab2741d2" style="display: inline; float: none; margin: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;">
<div style="border: #000080 1px solid; color: black; font-family: 'Courier New', Courier, Monospace; font-size: 10pt;">
<div style="background: #000080; color: white; font-family: Verdana, Tahoma, Arial, sans-serif; font-weight: bold; padding: 2px 5px;">
Clear notification (C#)</div>
<br />
<div style="background-color: white; overflow: auto; padding: 2px 5px; white-space: nowrap;">
<span style="background: #ffffff; color: blue;">var</span><span style="background: #ffffff; color: black;"> tile = </span><span style="background: #ffffff; color: #2b91af;">ShellTile</span><span style="background: #ffffff; color: black;">.ActiveTiles.First();</span><br />
<span style="color: blue; font-size: 10pt;">var</span><span style="color: black; font-size: 10pt;"> data = </span><span style="color: blue; font-size: 10pt;">new</span><span style="color: black; font-size: 10pt;"> </span><span style="color: #2b91af; font-size: 10pt;">FlipTileData</span><br />
<span style="font-size: 10pt;"> {</span><br />
<span style="font-size: 10pt;"> Count = 0,</span><br />
<span style="color: black; font-size: 10pt;"> Title = </span><span style="color: #a31515; font-size: 10pt;">"Lock Screen Demo"</span><br />
<span style="font-size: 10pt;"> };</span><br />
<span style="font-size: 10pt;">tile.Update(data);</span></div>
<br /></div>
<br /></div>
Pretty simple isn’t it?<br />
<br />
<strong>Testing on the Emulator </strong><br />
<br />
To test on the Windows Phone emulator you can use the <a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj206953(v=vs.105).aspx">Simulation Dashboard</a> which integrates directly into Visual Studio. To launch this, go to Tools –> Simulation Dashboard. You can use this tool to Lock and Unlock the emulator to test your apps lock screen integration<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgYLwAHNugkCrc4CrbqzMkqsGRFzTgN5ENfnxxo7nkIetK7V-sno0Z_G-QAzcIAzusnVnPe0mHDgdmdvuF__yVIrJHPGuOB5cVcDn66hhrd7CX39oHc5lBTj-mik0MLceBuUJQrdWdzsTm3/s1600-h/image%25255B3%25255D.png"><img alt="image" border="0" height="602" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhgcG2tKX96oPzd51qd8wBwW6vV93e6AsJqfKBI2afheUA6Ashy4bEFiJOYIox163ZCuSpM8adD1Kd08UGGd11S_MNSaOPWwwGG3HstmeF_mg79QUK8R2rGfOthLN0bd8EKTo3yVqJjIZst/?imgmax=800" style="border-bottom-width: 0px; border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; display: inline;" title="image" width="407" /></a><br />
<br />
I hope you found this interesting. You can grab the source code here<br />
<br />
<iframe frameborder="0" height="120" scrolling="no" src="https://skydrive.live.com/embed?cid=CA531E7FB4762C70&resid=CA531E7FB4762C70%2137080&authkey=AOXEBkTA6wCceKI" width="98"></iframe> Christian Resma Hellehttp://www.blogger.com/profile/16521776612083091477noreply@blogger.com0tag:blogger.com,1999:blog-4995334164049002857.post-9752027512193613322013-04-15T14:41:00.001+02:002019-06-11T18:56:03.181+02:00Using the Windows Phone Custom Contact Store<p>In previous versions of Windows Phone, you could always query the contact store to retrieve contact or calendar items. During that time I always wondered why I couldn’t just create my own contacts that can be shared with other applications and accessed through the People Hub. I guess more people had this problem and in Windows Phone 8 this has been addressed. Windows Phone 8 introduced the custom contact store in which apps can create contacts that are accessible from the People Hub and from other apps. Items in the custom contact store may only be modified by app that created them</p><p><strong>How to create contacts in Windows Phone 8</strong></p><p>In this section I would like to demonstrate how to use the custom contact store API. In order to do so we’ll create a UI that accepts the display name, email address, and mobile phone number. To make it a bit more fancy, we’ll add a feature that accepts a photo which can be loaded either from the camera or the media library</p><p>So here’s the code…</p><div id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:49bb3f99-6c74-44e1-b084-499dacdd45fa" class="wlWriterSmartContent" style="float: none; padding-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px"><div style="font-size: 10pt; border-top: #000080 1px solid; font-family: 'Courier New', courier, monospace; border-right: #000080 1px solid; border-bottom: #000080 1px solid; color: #000; border-left: #000080 1px solid"><div style="font-family: verdana, tahoma, arial, sans-serif; background: #000080; font-weight: bold; color: #fff; padding-bottom: 2px; padding-top: 2px; padding-left: 5px; padding-right: 5px">XAML</div><div style="overflow: auto; padding-bottom: 2px; padding-top: 2px; padding-left: 5px; padding-right: 5px; background-color: #ffffff"><span style="background: #ffffff; color: #0000ff"><</span><span style="background: #ffffff; color: #a31515">phone</span><span style="background: #ffffff; color: #0000ff">:</span><span style="background: #ffffff; color: #a31515">PhoneApplicationPage</span><span style="background: #ffffff; color: #ff0000"> x</span><span style="background: #ffffff; color: #0000ff">:</span><span style="background: #ffffff; color: #ff0000">Class</span><span style="background: #ffffff; color: #0000ff">="CustomContactStore.MainPage"</span> <br />
                           <span style="background: #ffffff; color: #000000"></span><span style="background: #ffffff; color: #ff0000"> xmlns</span><span style="background: #ffffff; color: #0000ff">="http://schemas.microsoft.com/winfx/2006/xaml/presentation"</span> <br />
                           <span style="background: #ffffff; color: #000000"></span><span style="background: #ffffff; color: #ff0000"> xmlns</span><span style="background: #ffffff; color: #0000ff">:</span><span style="background: #ffffff; color: #ff0000">x</span><span style="background: #ffffff; color: #0000ff">="http://schemas.microsoft.com/winfx/2006/xaml"</span> <br />
                           <span style="background: #ffffff; color: #000000"></span><span style="background: #ffffff; color: #ff0000"> xmlns</span><span style="background: #ffffff; color: #0000ff">:</span><span style="background: #ffffff; color: #ff0000">phone</span><span style="background: #ffffff; color: #0000ff">="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"</span> <br />
                           <span style="background: #ffffff; color: #000000"></span><span style="background: #ffffff; color: #ff0000"> xmlns</span><span style="background: #ffffff; color: #0000ff">:</span><span style="background: #ffffff; color: #ff0000">shell</span><span style="background: #ffffff; color: #0000ff">="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"</span> <br />
                           <span style="background: #ffffff; color: #000000"></span><span style="background: #ffffff; color: #ff0000"> xmlns</span><span style="background: #ffffff; color: #0000ff">:</span><span style="background: #ffffff; color: #ff0000">d</span><span style="background: #ffffff; color: #0000ff">="http://schemas.microsoft.com/expression/blend/2008"</span> <br />
                           <span style="background: #ffffff; color: #000000"></span><span style="background: #ffffff; color: #ff0000"> xmlns</span><span style="background: #ffffff; color: #0000ff">:</span><span style="background: #ffffff; color: #ff0000">mc</span><span style="background: #ffffff; color: #0000ff">="http://schemas.openxmlformats.org/markup-compatibility/2006"</span> <br />
                           <span style="background: #ffffff; color: #000000"></span><span style="background: #ffffff; color: #ff0000"> mc</span><span style="background: #ffffff; color: #0000ff">:</span><span style="background: #ffffff; color: #ff0000">Ignorable</span><span style="background: #ffffff; color: #0000ff">="d"</span> <br />
                           <span style="background: #ffffff; color: #000000"></span><span style="background: #ffffff; color: #ff0000"> FontFamily</span><span style="background: #ffffff; color: #0000ff">="{</span><span style="background: #ffffff; color: #a31515">StaticResource</span><span style="background: #ffffff; color: #ff0000"> PhoneFontFamilyNormal}</span><span style="background: #ffffff; color: #0000ff">"</span> <br />
                           <span style="background: #ffffff; color: #000000"></span><span style="background: #ffffff; color: #ff0000"> FontSize</span><span style="background: #ffffff; color: #0000ff">="{</span><span style="background: #ffffff; color: #a31515">StaticResource</span><span style="background: #ffffff; color: #ff0000"> PhoneFontSizeNormal}</span><span style="background: #ffffff; color: #0000ff">"</span> <br />
                           <span style="background: #ffffff; color: #000000"></span><span style="background: #ffffff; color: #ff0000"> Foreground</span><span style="background: #ffffff; color: #0000ff">="{</span><span style="background: #ffffff; color: #a31515">StaticResource</span><span style="background: #ffffff; color: #ff0000"> PhoneForegroundBrush}</span><span style="background: #ffffff; color: #0000ff">"</span> <br />
                           <span style="background: #ffffff; color: #000000"></span><span style="background: #ffffff; color: #ff0000"> SupportedOrientations</span><span style="background: #ffffff; color: #0000ff">="Portrait"</span> <br />
                           <span style="background: #ffffff; color: #000000"></span><span style="background: #ffffff; color: #ff0000"> Orientation</span><span style="background: #ffffff; color: #0000ff">="Portrait"</span> <br />
                           <span style="background: #ffffff; color: #000000"></span><span style="background: #ffffff; color: #ff0000"> shell</span><span style="background: #ffffff; color: #0000ff">:</span><span style="background: #ffffff; color: #ff0000">SystemTray.IsVisible</span><span style="background: #ffffff; color: #0000ff">="True"></span> <br />
<br />
    <span style="background: #ffffff; color: #000000"></span><span style="background: #ffffff; color: #0000ff"><</span><span style="background: #ffffff; color: #a31515">Grid</span><span style="background: #ffffff; color: #ff0000"> x</span><span style="background: #ffffff; color: #0000ff">:</span><span style="background: #ffffff; color: #ff0000">Name</span><span style="background: #ffffff; color: #0000ff">="LayoutRoot"</span><span style="background: #ffffff; color: #ff0000"> Background</span><span style="background: #ffffff; color: #0000ff">="Transparent"></span> <br />
        <span style="background: #ffffff; color: #000000"></span><span style="background: #ffffff; color: #0000ff"><</span><span style="background: #ffffff; color: #a31515">Grid.RowDefinitions</span><span style="background: #ffffff; color: #0000ff">></span> <br />
            <span style="background: #ffffff; color: #000000"></span><span style="background: #ffffff; color: #0000ff"><</span><span style="background: #ffffff; color: #a31515">RowDefinition</span><span style="background: #ffffff; color: #ff0000"> Height</span><span style="background: #ffffff; color: #0000ff">="Auto" /></span> <br />
            <span style="background: #ffffff; color: #000000"></span><span style="background: #ffffff; color: #0000ff"><</span><span style="background: #ffffff; color: #a31515">RowDefinition</span><span style="background: #ffffff; color: #ff0000"> Height</span><span style="background: #ffffff; color: #0000ff">="*" /></span> <br />
        <span style="background: #ffffff; color: #000000"></span><span style="background: #ffffff; color: #0000ff"></</span><span style="background: #ffffff; color: #a31515">Grid.RowDefinitions</span><span style="background: #ffffff; color: #0000ff">></span> <br />
<br />
        <span style="background: #ffffff; color: #000000"></span><span style="background: #ffffff; color: #0000ff"><</span><span style="background: #ffffff; color: #a31515">StackPanel</span><span style="background: #ffffff; color: #ff0000"> x</span><span style="background: #ffffff; color: #0000ff">:</span><span style="background: #ffffff; color: #ff0000">Name</span><span style="background: #ffffff; color: #0000ff">="TitlePanel"</span><span style="background: #ffffff; color: #ff0000"> Grid.Row</span><span style="background: #ffffff; color: #0000ff">="0"</span><span style="background: #ffffff; color: #ff0000"> Margin</span><span style="background: #ffffff; color: #0000ff">="12,17,0,28"></span> <br />
            <span style="background: #ffffff; color: #000000"></span><span style="background: #ffffff; color: #0000ff"><</span><span style="background: #ffffff; color: #a31515">TextBlock</span><span style="background: #ffffff; color: #ff0000"> Text</span><span style="background: #ffffff; color: #0000ff">="CUSTOM CONTACT STORE"</span><span style="background: #ffffff; color: #ff0000"> Style</span><span style="background: #ffffff; color: #0000ff">="{</span><span style="background: #ffffff; color: #a31515">StaticResource</span><span style="background: #ffffff; color: #ff0000"> PhoneTextNormalStyle}</span><span style="background: #ffffff; color: #0000ff">"</span><span style="background: #ffffff; color: #ff0000"> Margin</span><span style="background: #ffffff; color: #0000ff">="12,0" /></span> <br />
            <span style="background: #ffffff; color: #000000"></span><span style="background: #ffffff; color: #0000ff"><</span><span style="background: #ffffff; color: #a31515">TextBlock</span><span style="background: #ffffff; color: #ff0000"> Text</span><span style="background: #ffffff; color: #0000ff">="Sample"</span><span style="background: #ffffff; color: #ff0000"> Margin</span><span style="background: #ffffff; color: #0000ff">="9,-7,0,0"</span><span style="background: #ffffff; color: #ff0000"> Style</span><span style="background: #ffffff; color: #0000ff">="{</span><span style="background: #ffffff; color: #a31515">StaticResource</span><span style="background: #ffffff; color: #ff0000"> PhoneTextTitle1Style}</span><span style="background: #ffffff; color: #0000ff">" /></span> <br />
        <span style="background: #ffffff; color: #000000"></span><span style="background: #ffffff; color: #0000ff"></</span><span style="background: #ffffff; color: #a31515">StackPanel</span><span style="background: #ffffff; color: #0000ff">></span> <br />
<br />
        <span style="background: #ffffff; color: #000000"></span><span style="background: #ffffff; color: #0000ff"><</span><span style="background: #ffffff; color: #a31515">Grid</span><span style="background: #ffffff; color: #ff0000"> x</span><span style="background: #ffffff; color: #0000ff">:</span><span style="background: #ffffff; color: #ff0000">Name</span><span style="background: #ffffff; color: #0000ff">="ContentPanel"</span><span style="background: #ffffff; color: #ff0000"> Grid.Row</span><span style="background: #ffffff; color: #0000ff">="1"</span><span style="background: #ffffff; color: #ff0000"> Margin</span><span style="background: #ffffff; color: #0000ff">="12,0,12,0"></span> <br />
            <span style="background: #ffffff; color: #000000"></span><span style="background: #ffffff; color: #0000ff"><</span><span style="background: #ffffff; color: #a31515">StackPanel</span><span style="background: #ffffff; color: #0000ff">></span> <br />
                <span style="background: #ffffff; color: #000000"></span><span style="background: #ffffff; color: #0000ff"><</span><span style="background: #ffffff; color: #a31515">Grid</span><span style="background: #ffffff; color: #0000ff">></span> <br />
                    <span style="background: #ffffff; color: #000000"></span><span style="background: #ffffff; color: #0000ff"><</span><span style="background: #ffffff; color: #a31515">Grid.ColumnDefinitions</span><span style="background: #ffffff; color: #0000ff">></span> <br />
                        <span style="background: #ffffff; color: #000000"></span><span style="background: #ffffff; color: #0000ff"><</span><span style="background: #ffffff; color: #a31515">ColumnDefinition</span><span style="background: #ffffff; color: #ff0000"> Width</span><span style="background: #ffffff; color: #0000ff">="Auto" /></span> <br />
                        <span style="background: #ffffff; color: #000000"></span><span style="background: #ffffff; color: #0000ff"><</span><span style="background: #ffffff; color: #a31515">ColumnDefinition</span><span style="background: #ffffff; color: #ff0000"> Width</span><span style="background: #ffffff; color: #0000ff">="*" /></span> <br />
                    <span style="background: #ffffff; color: #000000"></span><span style="background: #ffffff; color: #0000ff"></</span><span style="background: #ffffff; color: #a31515">Grid.ColumnDefinitions</span><span style="background: #ffffff; color: #0000ff">></span> <br />
                    <span style="background: #ffffff; color: #000000"></span><span style="background: #ffffff; color: #0000ff"><</span><span style="background: #ffffff; color: #a31515">Grid.RowDefinitions</span><span style="background: #ffffff; color: #0000ff">></span> <br />
                        <span style="background: #ffffff; color: #000000"></span><span style="background: #ffffff; color: #0000ff"><</span><span style="background: #ffffff; color: #a31515">RowDefinition</span><span style="background: #ffffff; color: #0000ff"> /></span> <br />
                        <span style="background: #ffffff; color: #000000"></span><span style="background: #ffffff; color: #0000ff"><</span><span style="background: #ffffff; color: #a31515">RowDefinition</span><span style="background: #ffffff; color: #0000ff"> /></span> <br />
                        <span style="background: #ffffff; color: #000000"></span><span style="background: #ffffff; color: #0000ff"><</span><span style="background: #ffffff; color: #a31515">RowDefinition</span><span style="background: #ffffff; color: #0000ff"> /></span> <br />
                        <span style="background: #ffffff; color: #000000"></span><span style="background: #ffffff; color: #0000ff"><</span><span style="background: #ffffff; color: #a31515">RowDefinition</span><span style="background: #ffffff; color: #0000ff"> /></span> <br />
                    <span style="background: #ffffff; color: #000000"></span><span style="background: #ffffff; color: #0000ff"></</span><span style="background: #ffffff; color: #a31515">Grid.RowDefinitions</span><span style="background: #ffffff; color: #0000ff">></span> <br />
                    <span style="background: #ffffff; color: #000000"></span><span style="background: #ffffff; color: #0000ff"><</span><span style="background: #ffffff; color: #a31515">TextBlock</span><span style="background: #ffffff; color: #ff0000"> Text</span><span style="background: #ffffff; color: #0000ff">="Display Name"</span><span style="background: #ffffff; color: #ff0000"> VerticalAlignment</span><span style="background: #ffffff; color: #0000ff">="Center" /></span> <br />
                    <span style="background: #ffffff; color: #000000"></span><span style="background: #ffffff; color: #0000ff"><</span><span style="background: #ffffff; color: #a31515">TextBox</span><span style="background: #ffffff; color: #ff0000"> Grid.Column</span><span style="background: #ffffff; color: #0000ff">="1"</span><span style="background: #ffffff; color: #ff0000"> Name</span><span style="background: #ffffff; color: #0000ff">="displayName" /></span> <br />
                    <span style="background: #ffffff; color: #000000"></span><span style="background: #ffffff; color: #0000ff"><</span><span style="background: #ffffff; color: #a31515">TextBlock</span><span style="background: #ffffff; color: #ff0000"> Grid.Row</span><span style="background: #ffffff; color: #0000ff">="1"</span><span style="background: #ffffff; color: #ff0000"> Text</span><span style="background: #ffffff; color: #0000ff">="Email"</span><span style="background: #ffffff; color: #ff0000"> VerticalAlignment</span><span style="background: #ffffff; color: #0000ff">="Center" /></span> <br />
                    <span style="background: #ffffff; color: #000000"></span><span style="background: #ffffff; color: #0000ff"><</span><span style="background: #ffffff; color: #a31515">TextBox</span><span style="background: #ffffff; color: #ff0000"> Grid.Row</span><span style="background: #ffffff; color: #0000ff">="1"</span><span style="background: #ffffff; color: #ff0000"> Grid.Column</span><span style="background: #ffffff; color: #0000ff">="1"</span><span style="background: #ffffff; color: #ff0000"> Name</span><span style="background: #ffffff; color: #0000ff">="email" /></span> <br />
                    <span style="background: #ffffff; color: #000000"></span><span style="background: #ffffff; color: #0000ff"><</span><span style="background: #ffffff; color: #a31515">TextBlock</span><span style="background: #ffffff; color: #ff0000"> Grid.Row</span><span style="background: #ffffff; color: #0000ff">="2"</span><span style="background: #ffffff; color: #ff0000"> VerticalAlignment</span><span style="background: #ffffff; color: #0000ff">="Center"</span><span style="background: #ffffff; color: #ff0000"> Text</span><span style="background: #ffffff; color: #0000ff">="Mobile" /></span> <br />
                    <span style="background: #ffffff; color: #000000"></span><span style="background: #ffffff; color: #0000ff"><</span><span style="background: #ffffff; color: #a31515">TextBox</span><span style="background: #ffffff; color: #ff0000"> Grid.Row</span><span style="background: #ffffff; color: #0000ff">="2"</span><span style="background: #ffffff; color: #ff0000"> Grid.Column</span><span style="background: #ffffff; color: #0000ff">="1"</span><span style="background: #ffffff; color: #ff0000"> Name</span><span style="background: #ffffff; color: #0000ff">="mobile" /></span> <br />
                <span style="background: #ffffff; color: #000000"></span><span style="background: #ffffff; color: #0000ff"></</span><span style="background: #ffffff; color: #a31515">Grid</span><span style="background: #ffffff; color: #0000ff">></span> <br />
                <span style="background: #ffffff; color: #000000"></span><span style="background: #ffffff; color: #0000ff"><</span><span style="background: #ffffff; color: #a31515">Button</span><span style="background: #ffffff; color: #ff0000"> Content</span><span style="background: #ffffff; color: #0000ff">="Attach New Photo"</span><span style="background: #ffffff; color: #ff0000"> Click</span><span style="background: #ffffff; color: #0000ff">="AttachNewPhotoClicked" /></span> <br />
                <span style="background: #ffffff; color: #000000"></span><span style="background: #ffffff; color: #0000ff"><</span><span style="background: #ffffff; color: #a31515">Button</span><span style="background: #ffffff; color: #ff0000"> Content</span><span style="background: #ffffff; color: #0000ff">="Attach Existing Photo"</span><span style="background: #ffffff; color: #ff0000"> Click</span><span style="background: #ffffff; color: #0000ff">="AttachExistingPhotoClicked" /></span> <br />
                <span style="background: #ffffff; color: #000000"></span><span style="background: #ffffff; color: #0000ff"><</span><span style="background: #ffffff; color: #a31515">Button</span><span style="background: #ffffff; color: #ff0000"> Content</span><span style="background: #ffffff; color: #0000ff">="Save Contact"</span><span style="background: #ffffff; color: #ff0000"> Click</span><span style="background: #ffffff; color: #0000ff">="AddClicked" /></span> <br />
            <span style="background: #ffffff; color: #000000"></span><span style="background: #ffffff; color: #0000ff"></</span><span style="background: #ffffff; color: #a31515">StackPanel</span><span style="background: #ffffff; color: #0000ff">></span> <br />
        <span style="background: #ffffff; color: #000000"></span><span style="background: #ffffff; color: #0000ff"></</span><span style="background: #ffffff; color: #a31515">Grid</span><span style="background: #ffffff; color: #0000ff">></span> <br />
    <span style="background: #ffffff; color: #000000"></span><span style="background: #ffffff; color: #0000ff"></</span><span style="background: #ffffff; color: #a31515">Grid</span><span style="background: #ffffff; color: #0000ff">></span> <br />
<br />
<span style="background: #ffffff; color: #0000ff"></</span><span style="background: #ffffff; color: #a31515">phone</span><span style="background: #ffffff; color: #0000ff">:</span><span style="background: #ffffff; color: #a31515">PhoneApplicationPage</span><span style="background: #ffffff; color: #0000ff">></span></div></div></div><p></p><div id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:97f4a02f-47ac-4d9d-bdff-8fc24f7714e1" class="wlWriterSmartContent" style="float: none; padding-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px"><div style="font-size: 10pt; border-top: #000080 1px solid; font-family: 'Courier New', courier, monospace; border-right: #000080 1px solid; border-bottom: #000080 1px solid; color: #000; border-left: #000080 1px solid"><div style="font-family: verdana, tahoma, arial, sans-serif; background: #000080; font-weight: bold; color: #fff; padding-bottom: 2px; padding-top: 2px; padding-left: 5px; padding-right: 5px">Code Behind (C#)</div><div style="overflow: auto; padding-bottom: 2px; padding-top: 2px; padding-left: 5px; padding-right: 5px; background-color: #ffffff"><span style="background: #ffffff; color: #0000ff">using</span><span style="background: #ffffff; color: #000000"> System;</span> <br />
<span style="background: #ffffff; color: #0000ff">using</span><span style="background: #ffffff; color: #000000"> System.IO;</span> <br />
<span style="background: #ffffff; color: #0000ff">using</span><span style="background: #ffffff; color: #000000"> System.Linq;</span> <br />
<span style="background: #ffffff; color: #0000ff">using</span><span style="background: #ffffff; color: #000000"> System.Windows;</span> <br />
<span style="background: #ffffff; color: #0000ff">using</span><span style="background: #ffffff; color: #000000"> System.Windows.Controls;</span> <br />
<span style="background: #ffffff; color: #0000ff">using</span><span style="background: #ffffff; color: #000000"> Microsoft.Phone.Tasks;</span> <br />
<span style="background: #ffffff; color: #0000ff">using</span><span style="background: #ffffff; color: #000000"> Windows.Phone.PersonalInformation;</span> <br />
<br />
<span style="background: #ffffff; color: #0000ff">namespace</span><span style="background: #ffffff; color: #000000"> CustomContactStore</span> <br />
<span style="background: #ffffff; color: #000000">{</span> <br />
    <span style="background: #ffffff; color: #000000"></span><span style="background: #ffffff; color: #0000ff">public</span><span style="background: #ffffff; color: #000000"> </span><span style="background: #ffffff; color: #0000ff">partial</span><span style="background: #ffffff; color: #000000"> </span><span style="background: #ffffff; color: #0000ff">class</span><span style="background: #ffffff; color: #000000"> </span><span style="background: #ffffff; color: #2b91af">MainPage</span> <br />
    <span style="background: #ffffff; color: #000000">{</span> <br />
        <span style="background: #ffffff; color: #000000"></span><span style="background: #ffffff; color: #0000ff">private</span><span style="background: #ffffff; color: #000000"> </span><span style="background: #ffffff; color: #2b91af">Stream</span><span style="background: #ffffff; color: #000000"> photo;</span> <br />
<br />
        <span style="background: #ffffff; color: #000000"></span><span style="background: #ffffff; color: #0000ff">public</span><span style="background: #ffffff; color: #000000"> MainPage()</span> <br />
        <span style="background: #ffffff; color: #000000">{</span> <br />
            <span style="background: #ffffff; color: #000000">InitializeComponent();</span> <br />
        <span style="background: #ffffff; color: #000000">}</span> <br />
<br />
        <span style="background: #ffffff; color: #000000"></span><span style="background: #ffffff; color: #0000ff">private</span><span style="background: #ffffff; color: #000000"> </span><span style="background: #ffffff; color: #0000ff">async</span><span style="background: #ffffff; color: #000000"> </span><span style="background: #ffffff; color: #0000ff">void</span><span style="background: #ffffff; color: #000000"> AddClicked(</span><span style="background: #ffffff; color: #0000ff">object</span><span style="background: #ffffff; color: #000000"> sender, </span><span style="background: #ffffff; color: #2b91af">RoutedEventArgs</span><span style="background: #ffffff; color: #000000"> e)</span> <br />
        <span style="background: #ffffff; color: #000000">{</span> <br />
            <span style="background: #ffffff; color: #000000"></span><span style="background: #ffffff; color: #0000ff">var</span><span style="background: #ffffff; color: #000000"> store = </span><span style="background: #ffffff; color: #0000ff">await</span><span style="background: #ffffff; color: #000000"> </span><span style="background: #ffffff; color: #2b91af">ContactStore</span><span style="background: #ffffff; color: #000000">.CreateOrOpenAsync();</span> <br />
            <span style="background: #ffffff; color: #000000"></span><span style="background: #ffffff; color: #0000ff">var</span><span style="background: #ffffff; color: #000000"> contact = </span><span style="background: #ffffff; color: #0000ff">new</span><span style="background: #ffffff; color: #000000"> </span><span style="background: #ffffff; color: #2b91af">StoredContact</span><span style="background: #ffffff; color: #000000">(store)</span> <br />
                              <span style="background: #ffffff; color: #000000">{</span> <br />
                                  <span style="background: #ffffff; color: #000000">DisplayName = displayName.Text</span> <br />
                              <span style="background: #ffffff; color: #000000">};</span> <br />
<br />
            <span style="background: #ffffff; color: #000000"></span><span style="background: #ffffff; color: #0000ff">var</span><span style="background: #ffffff; color: #000000"> props = </span><span style="background: #ffffff; color: #0000ff">await</span><span style="background: #ffffff; color: #000000"> contact.GetPropertiesAsync();</span> <br />
            <span style="background: #ffffff; color: #000000">props.Add(</span><span style="background: #ffffff; color: #2b91af">KnownContactProperties</span><span style="background: #ffffff; color: #000000">.Email, email.Text);</span> <br />
            <span style="background: #ffffff; color: #000000">props.Add(</span><span style="background: #ffffff; color: #2b91af">KnownContactProperties</span><span style="background: #ffffff; color: #000000">.MobileTelephone, mobile.Text);</span> <br />
<br />
            <span style="background: #ffffff; color: #000000"></span><span style="background: #ffffff; color: #0000ff">if</span><span style="background: #ffffff; color: #000000"> (photo != </span><span style="background: #ffffff; color: #0000ff">null</span><span style="background: #ffffff; color: #000000">)</span> <br />
                <span style="background: #ffffff; color: #000000"></span><span style="background: #ffffff; color: #0000ff">await</span><span style="background: #ffffff; color: #000000"> contact.SetDisplayPictureAsync(photo.AsInputStream());</span> <br />
<br />
            <span style="background: #ffffff; color: #000000"></span><span style="background: #ffffff; color: #0000ff">await</span><span style="background: #ffffff; color: #000000"> contact.SaveAsync();</span> <br />
<br />
            <span style="background: #ffffff; color: #000000"></span><span style="background: #ffffff; color: #0000ff">if</span><span style="background: #ffffff; color: #000000"> (photo != </span><span style="background: #ffffff; color: #0000ff">null</span><span style="background: #ffffff; color: #000000">)</span> <br />
                <span style="background: #ffffff; color: #000000">photo.Dispose();</span> <br />
        <span style="background: #ffffff; color: #000000">}</span> <br />
<br />
        <span style="background: #ffffff; color: #000000"></span><span style="background: #ffffff; color: #0000ff">private</span><span style="background: #ffffff; color: #000000"> </span><span style="background: #ffffff; color: #0000ff">void</span><span style="background: #ffffff; color: #000000"> AttachNewPhotoClicked(</span><span style="background: #ffffff; color: #0000ff">object</span><span style="background: #ffffff; color: #000000"> sender, </span><span style="background: #ffffff; color: #2b91af">RoutedEventArgs</span><span style="background: #ffffff; color: #000000"> e)</span> <br />
        <span style="background: #ffffff; color: #000000">{</span> <br />
            <span style="background: #ffffff; color: #000000"></span><span style="background: #ffffff; color: #0000ff">var</span><span style="background: #ffffff; color: #000000"> task = </span><span style="background: #ffffff; color: #0000ff">new</span><span style="background: #ffffff; color: #000000"> </span><span style="background: #ffffff; color: #2b91af">CameraCaptureTask</span><span style="background: #ffffff; color: #000000">();</span> <br />
            <span style="background: #ffffff; color: #000000">task.Completed += OnTaskOnCompleted;</span> <br />
            <span style="background: #ffffff; color: #000000">task.Show();</span> <br />
        <span style="background: #ffffff; color: #000000">}</span> <br />
<br />
        <span style="background: #ffffff; color: #000000"></span><span style="background: #ffffff; color: #0000ff">private</span><span style="background: #ffffff; color: #000000"> </span><span style="background: #ffffff; color: #0000ff">void</span><span style="background: #ffffff; color: #000000"> OnTaskOnCompleted(</span><span style="background: #ffffff; color: #0000ff">object</span><span style="background: #ffffff; color: #000000"> o, </span><span style="background: #ffffff; color: #2b91af">PhotoResult</span><span style="background: #ffffff; color: #000000"> result)</span> <br />
        <span style="background: #ffffff; color: #000000">{</span> <br />
            <span style="background: #ffffff; color: #000000">photo = result.ChosenPhoto;</span> <br />
        <span style="background: #ffffff; color: #000000">}</span> <br />
<br />
        <span style="background: #ffffff; color: #000000"></span><span style="background: #ffffff; color: #0000ff">private</span><span style="background: #ffffff; color: #000000"> </span><span style="background: #ffffff; color: #0000ff">void</span><span style="background: #ffffff; color: #000000"> AttachExistingPhotoClicked(</span><span style="background: #ffffff; color: #0000ff">object</span><span style="background: #ffffff; color: #000000"> sender, </span><span style="background: #ffffff; color: #2b91af">RoutedEventArgs</span><span style="background: #ffffff; color: #000000"> e)</span> <br />
        <span style="background: #ffffff; color: #000000">{</span> <br />
            <span style="background: #ffffff; color: #000000"></span><span style="background: #ffffff; color: #0000ff">var</span><span style="background: #ffffff; color: #000000"> task = </span><span style="background: #ffffff; color: #0000ff">new</span><span style="background: #ffffff; color: #000000"> </span><span style="background: #ffffff; color: #2b91af">PhotoChooserTask</span><span style="background: #ffffff; color: #000000">();</span> <br />
            <span style="background: #ffffff; color: #000000">task.Completed += OnTaskOnCompleted;</span> <br />
            <span style="background: #ffffff; color: #000000">task.Show();</span> <br />
        <span style="background: #ffffff; color: #000000">}</span> <br />
    <span style="background: #ffffff; color: #000000">}</span> <br />
<span style="background: #ffffff; color: #000000">}</span></div></div></div><p></p><p>To create a custom contact we need to use the <a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj207529(v=vs.105).aspx">ContactStore</a> API, we create an instance of this using the helper method <a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj207576(v=vs.105).aspx">CreateOrOpenAsync()</a>. Now that we have an instance of the contact store, we create an instance of a <a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj207727(v=vs.105).aspx">StoredContact</a> and set the DisplayName property to the value of the display name entered in the UI. The StoredContact object is very limited but we can add <a href="http://msdn.microsoft.com/en-US/library/windowsphone/develop/windows.phone.personalinformation.knowncontactproperties(v=vs.105).aspx">KnownContactProperties</a> such as Email and MobileTelephone. This is done by using the <a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/windows.phone.personalinformation.storedcontact.getpropertiesasync(v=vs.105).aspx">GetPropertiesAsync()</a> method of the StoredContact instance. The photos can be attached using the <a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/hh394006(v=vs.105).aspx">CameraCaptureTask</a> or the <a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/hh394019(v=vs.105).aspx">PhotoChooserTask</a>. We attach the photos by calling the <a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/windows.phone.personalinformation.storedcontact.getdisplaypictureasync(v=vs.105).aspx">SetDisplayPictureAsync()</a> method of the StoredContact instance. The API’s for the custom contact store are pretty straight forward and easy to use.</p><p><strong>Manifest</strong></p><p>The custom contact store requires the ID_CAP_CONTACTS capability, we should enable that in the WMAppManifest.xml file. In order to that, in the Visual Studio Solution Explorer, expand the project properties folder and double click the WMAppManifest.xml file. This will open the new UI editor for the manifest file. Go to the Capabilities tab and enable the ID_CAP_CONTACTS</p><p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhTt3AkYi9SB5lDGvwlrOA4XWPOkKlOyy1uh8PcyvrKJdTjBie_zLR5gYdxE4EGO_L1ZYYHpoCJ8GhAXVYWHl_FAZ9YAAWkYt-LPl1mInVXCfNmTu0_jWlypa5vfqCK5NobLmqjc02rhE4z/s1600-h/id_cap_contacts%25255B4%25255D.png"><img title="id_cap_contacts" style="border-left-width: 0px; border-right-width: 0px; border-bottom-width: 0px; display: inline; border-top-width: 0px" border="0" alt="id_cap_contacts" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAV9KPcvskGUmkFNoB7uIhzSM6HlbtoSZiTeQeC9bTEkGlCcifl86xI-ttGwBWw0Ib34rnQBG2Y869PyXdkxeEQa7ZnYD4mKePO0-XjdVxErKIWZPtAZCeaPPHmPbu40-hDlRlelILPMrr/?imgmax=800" width="592" height="332" /></a> </p><p>Once the manifest file has been updated the app should be able to launch.</p><p>The user interface looks like this:</p><p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEic8ITQV66umjz-aDXdhRDo7t7vU1xnvZbQAkWTVSsjowbAdEwVECa4aDuF1Khvp_k2VBrZfof03MwO4YjDMHAuTNf64cdkrWmUChWbifyXu1q4q8GKudZYAotMT9uoOmmQIekovyS4beNr/s1600-h/Custom%252520Contact%252520Store%25255B24%25255D.png"><img title="Custom Contact Store" style="border-left-width: 0px; border-right-width: 0px; border-bottom-width: 0px; display: inline; border-top-width: 0px" border="0" alt="Custom Contact Store" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfraHDyVEU5Uo7FBtXkftSyQmnPv7iU0x7n4xmDNVfRfqo_i5rNx2hVmSUiSFYIz1btln6d1UtO5tsZNJELjJ_701Cby-y7I1WmxFrIsCN1_lgZD5W8gTGv3MJk_6tFUMdANxttNYEclP6/?imgmax=800" width="404" height="649" /></a> </p><p>Once the contact is created it will be available in the People Hub</p><p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjRfcmQ1ywBwmdI-fy36Grh1xiyReg93S_sRKxaZuFQEnA1B3cUK2LqbOHLTf8E8V6eqKF4Di-iM6ZvOoeH8peL-2B3a7h5fzp2v2rzMsVtljrK-_5AvM_2M3cJVhBOpF2ui124mBHYxYnQ/s1600-h/People%252520Hub%25255B7%25255D.png"><img title="People Hub" style="border-left-width: 0px; border-right-width: 0px; border-bottom-width: 0px; display: inline; border-top-width: 0px" border="0" alt="People Hub" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjYeVkoDl77ws6pvSCcNuD5i8q95z0bQycn4oROuTrdpWTPy1F3tPRPB6-WSScrmQDD25ASa6pzBxR9ySXmgt-juCRYYX0xgEfDY3mYdF394eSqdplExmT5-LwbrGw28CY4-5cCq73zxon7/?imgmax=800" width="404" height="650" /></a></p><p>When the contact is viewed from the People Hub the owner of the contact will be displayed on top </p><p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4XlVlZvZn4qfTM4XPfmLHTq9fld3IP_64wdX6LJFzTSLwMIsAQJGh_sA-J7fBQgcm9MS0ZbZCE5I3qa9IFaB0zDruq5wkK5GeRz1B0OI7diplCJ9B2JdbpMrHBSjVHmTxoQq_1I0sbK9x/s1600-h/Custom%252520Contact%25255B3%25255D.png"><img title="Custom Contact" style="border-left-width: 0px; border-right-width: 0px; border-bottom-width: 0px; display: inline; border-top-width: 0px" border="0" alt="Custom Contact" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLo849CVkaGlkK8YFIn0TQcyiR-eXgoqLhW7aR-rzhsZSg0a-lm-qFkXrDCSH5rwmp5yQe0QLgT8Z9BC4WddpOYng53dbvA6waMBXlzhv8LrGzq_Ukbx9wAuhnnd3WDdSVTmggvb1x139o/?imgmax=800" width="404" height="671" /></a> </p><p>I hope you found this useful. You can check out the source code using the link below</p><iframe height="120" src="https://skydrive.live.com/embed?cid=CA531E7FB4762C70&resid=CA531E7FB4762C70%2136984&authkey=AE6ctkxSOjg-Xgo" frameborder="0" width="98" scrolling="no"></iframe> Christian Resma Hellehttp://www.blogger.com/profile/16521776612083091477noreply@blogger.com3tag:blogger.com,1999:blog-4995334164049002857.post-84902608602098851782013-01-18T14:55:00.000+01:002013-01-18T14:55:41.750+01:00The missing ResWFileCodeGenerator custom tool for Visual Studio 2012I've been doing quite a lot of Windows Store Apps on Windows 8 lately. Ever since I started I always seemed to miss the ResXFileCodeGenerator custom tool. This is because in WinRT when you want to load a localized string in code then you will have to do something like this:<br />
<br />
<pre class="csharpcode" style="background-color: white; font-family: Consolas, 'Courier New', Courier, monospace; font-size: small;"><span class="kwrd" style="color: blue;">var</span> resources = <span class="kwrd" style="color: blue;">new</span> ResourceLoader();
<span class="kwrd" style="color: blue;">var</span> localizedString = resources.GetString(<span class="str" style="color: #a31515;">"SomeResourceName"</span>);</pre>
<br />
This of course can easily lead to a lot of errors. In my case I got a little to eager while refactoring and forgot to notice that I was also changing hard coded strings. This broke the code quite a lot. Because of this frustration I decided to implement my own custom tool since Microsoft didn't provide one<br />
<br />
The project is open source and is available at <a href="http://reswcodegen.codeplex.com/" target="_blank">CodePlex</a>. Here's a preview of the description which I took directly from my CodePlex project site.<br />
<br />
<div class="WikiContent" id="WikiContent" style="border: 0px; color: #253340; font-family: 'Segoe UI', Tahoma, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19.015625px; margin: 15px 0px 0px; outline: 0px; padding: 0px; vertical-align: baseline; width: 650px; word-wrap: break-word;">
<div class="wikidoc" style="border: 0px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">
<b style="border: 0px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Project Description</b><br />
A Visual Studio 2012 Custom Tool for generating a strongly typed helper class for accessing localized resources from a .ResW file.<br />
<br />
<b style="border: 0px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Features</b><br />
- C# code generator<br />
- VB.NET code generator<br />
<br />
<br />
<b style="border: 0px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Visual Studio 2012 Custom Tool (C#)</b><br />
<img src="http://www.codeplex.com/Download?ProjectName=reswcodegen&DownloadId=527605" style="border: 0px; margin: 0px; max-width: 100%; outline: 0px; padding: 0px; vertical-align: baseline;" /><br />
<br />
<b style="border: 0px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Visual Studio 2012 Custom Tool (VB)</b><br />
<img src="http://www.codeplex.com/Download?ProjectName=reswcodegen&DownloadId=528704" style="border: 0px; margin: 0px; max-width: 100%; outline: 0px; padding: 0px; vertical-align: baseline;" /><br />
<br />
<b style="border: 0px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Resource File Contents</b><br />
<img src="http://www.codeplex.com/Download?ProjectName=reswcodegen&DownloadId=527606" style="border: 0px; margin: 0px; max-width: 100%; outline: 0px; padding: 0px; vertical-align: baseline;" /><br />
<br />
<b style="border: 0px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">C# Usage</b><br />
<div style="background-color: white; border: 0px; color: black; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">
<pre style="background-color: rgb(236, 236, 236) !important; border: 0.1em dashed rgb(62, 98, 166) !important; font-family: Consolas, 'Courier New', Courier, monospace !important; font-size: 1em !important; height: auto; margin-bottom: 20px; outline: 0px; overflow: hidden; padding: 0.5em 0.5em 1.5em; vertical-align: baseline; white-space: pre-wrap;"><span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">private</span> <span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">string</span> test1, test2, test3;
<span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">private</span> <span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">void</span> LoadLocalizedStrings()
{
test1 = App1.LocalizedResources.Resources.Test1;
test2 = App1.LocalizedResources.Resources.Test2;
test3 = App1.LocalizedResources.Resources.Test3;
}
</pre>
</div>
<br />
<b style="border: 0px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Visual Basic Usage</b><br />
<div style="background-color: white; border: 0px; color: black; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">
<pre style="background-color: rgb(236, 236, 236) !important; border: 0.1em dashed rgb(62, 98, 166) !important; font-family: Consolas, 'Courier New', Courier, monospace !important; font-size: 1em !important; height: auto; margin-bottom: 20px; outline: 0px; overflow: hidden; padding: 0.5em 0.5em 1.5em; vertical-align: baseline; white-space: pre-wrap;"><span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Dim</span> test1, test2, test3
<span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Private</span> <span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Sub</span> LoadLocalizedStrings()
test1 = AppVb.LocalizedStrings.Resources.Test1
test2 = AppVb.LocalizedStrings.Resources.Test2
test3 = AppVb.LocalizedStrings.Resources.Test3
<span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">End</span> <span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Sub</span>
</pre>
</div>
<br />
<b style="border: 0px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Generated C# Code</b><br />
<div style="background-color: white; border: 0px; color: black; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">
<pre style="background-color: rgb(236, 236, 236) !important; border: 0.1em dashed rgb(62, 98, 166) !important; font-family: Consolas, 'Courier New', Courier, monospace !important; font-size: 1em !important; height: auto; margin-bottom: 20px; outline: 0px; overflow: hidden; padding: 0.5em 0.5em 1.5em; vertical-align: baseline; white-space: pre-wrap;"><span style="background-color: transparent; border: 0px; color: green; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">//------------------------------------------------------------------------------</span>
<span style="background-color: transparent; border: 0px; color: green; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">// <auto-generated></span>
<span style="background-color: transparent; border: 0px; color: green; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">// This code was generated by a tool.</span>
<span style="background-color: transparent; border: 0px; color: green; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">// Runtime Version:4.0.30319.18010</span>
<span style="background-color: transparent; border: 0px; color: green; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">//</span>
<span style="background-color: transparent; border: 0px; color: green; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">// Changes to this file may cause incorrect behavior and will be lost if</span>
<span style="background-color: transparent; border: 0px; color: green; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">// the code is regenerated.</span>
<span style="background-color: transparent; border: 0px; color: green; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">// </auto-generated></span>
<span style="background-color: transparent; border: 0px; color: green; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">//------------------------------------------------------------------------------</span>
<span style="background-color: transparent; border: 0px; color: green; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">// --------------------------------------------------------------------------------------------------</span>
<span style="background-color: transparent; border: 0px; color: green; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">// <auto-generatedInfo></span>
<span style="background-color: transparent; border: 0px; color: green; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">// This code was generated by ResW File Code Generator (http://reswcodegen.codeplex.com)</span>
<span style="background-color: transparent; border: 0px; color: green; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">// ResW File Code Generator was written by Christian Resma Helle</span>
<span style="background-color: transparent; border: 0px; color: green; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">// and is under GNU General Public License version 2 (GPLv2)</span>
<span style="background-color: transparent; border: 0px; color: green; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">// </span>
<span style="background-color: transparent; border: 0px; color: green; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">// This code contains a helper class exposing property representations</span>
<span style="background-color: transparent; border: 0px; color: green; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">// of the string resources defined in the specified .ResW file</span>
<span style="background-color: transparent; border: 0px; color: green; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">// </span>
<span style="background-color: transparent; border: 0px; color: green; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">// Generated: 11/08/2012 22:41:22</span>
<span style="background-color: transparent; border: 0px; color: green; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">// </auto-generatedInfo></span>
<span style="background-color: transparent; border: 0px; color: green; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">// --------------------------------------------------------------------------------------------------</span>
<span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">namespace</span> App1.LocalizedResources
{
<span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">using</span> Windows.ApplicationModel.Resources;
<span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">public</span> <span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">partial</span> <span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">class</span> Resources
{
<span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">private</span> <span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">static</span> ResourceLoader resourceLoader = <span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">new</span> ResourceLoader();
<span style="background-color: transparent; border: 0px; color: grey; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">///</span> <span style="background-color: transparent; border: 0px; color: grey; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;"><summary></span>
<span style="background-color: transparent; border: 0px; color: grey; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">///</span><span style="background-color: transparent; border: 0px; color: green; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;"> Localized resource similar to "Test 1 value"</span>
<span style="background-color: transparent; border: 0px; color: grey; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">///</span> <span style="background-color: transparent; border: 0px; color: grey; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;"></summary></span>
<span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">public</span> <span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">static</span> <span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">string</span> Test1
{
<span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">get</span>
{
<span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">return</span> resourceLoader.GetString(<span style="background-color: transparent; border: 0px; color: #a31515; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">"Test1"</span>);
}
}
<span style="background-color: transparent; border: 0px; color: grey; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">///</span> <span style="background-color: transparent; border: 0px; color: grey; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;"><summary></span>
<span style="background-color: transparent; border: 0px; color: grey; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">///</span><span style="background-color: transparent; border: 0px; color: green; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;"> Localized resource similar to "Test 2 value"</span>
<span style="background-color: transparent; border: 0px; color: grey; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">///</span> <span style="background-color: transparent; border: 0px; color: grey; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;"></summary></span>
<span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">public</span> <span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">static</span> <span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">string</span> Test2
{
<span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">get</span>
{
<span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">return</span> resourceLoader.GetString(<span style="background-color: transparent; border: 0px; color: #a31515; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">"Test2"</span>);
}
}
<span style="background-color: transparent; border: 0px; color: grey; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">///</span> <span style="background-color: transparent; border: 0px; color: grey; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;"><summary></span>
<span style="background-color: transparent; border: 0px; color: grey; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">///</span><span style="background-color: transparent; border: 0px; color: green; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;"> Localized resource similar to "Test 3 value"</span>
<span style="background-color: transparent; border: 0px; color: grey; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">///</span> <span style="background-color: transparent; border: 0px; color: grey; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;"></summary></span>
<span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">public</span> <span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">static</span> <span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">string</span> Test3
{
<span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">get</span>
{
<span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">return</span> resourceLoader.GetString(<span style="background-color: transparent; border: 0px; color: #a31515; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">"Test3"</span>);
}
}
}
}
</pre>
</div>
<br />
<b style="border: 0px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Generated Visual Basic Code</b><br />
<div style="background-color: white; border: 0px; color: black; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">
<pre style="background-color: rgb(236, 236, 236) !important; border: 0.1em dashed rgb(62, 98, 166) !important; font-family: Consolas, 'Courier New', Courier, monospace !important; font-size: 1em !important; height: auto; margin-bottom: 20px; outline: 0px; overflow: hidden; padding: 0.5em 0.5em 1.5em; vertical-align: baseline; white-space: pre-wrap;"><span style="background-color: transparent; border: 0px; color: green; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">'------------------------------------------------------------------------------</span>
<span style="background-color: transparent; border: 0px; color: green; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">' <auto-generated></span>
<span style="background-color: transparent; border: 0px; color: green; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">' This code was generated by a tool.</span>
<span style="background-color: transparent; border: 0px; color: green; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">' Runtime Version:4.0.30319.18010</span>
<span style="background-color: transparent; border: 0px; color: green; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">'</span>
<span style="background-color: transparent; border: 0px; color: green; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">' Changes to this file may cause incorrect behavior and will be lost if</span>
<span style="background-color: transparent; border: 0px; color: green; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">' the code is regenerated.</span>
<span style="background-color: transparent; border: 0px; color: green; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">' </auto-generated></span>
<span style="background-color: transparent; border: 0px; color: green; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">'------------------------------------------------------------------------------</span>
<span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Option</span> Strict <span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Off</span>
<span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Option</span> <span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Explicit</span> <span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">On</span>
<span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Imports</span> Windows.ApplicationModel.Resources
<span style="background-color: transparent; border: 0px; color: green; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">'--------------------------------------------------------------------------------------------------</span>
<span style="background-color: transparent; border: 0px; color: green; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">'<auto-generatedInfo></span>
<span style="background-color: transparent; border: 0px; color: green; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">' This code was generated by ResW File Code Generator (http://reswcodegen.codeplex.com)</span>
<span style="background-color: transparent; border: 0px; color: green; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">' ResW File Code Generator was written by Christian Resma Helle</span>
<span style="background-color: transparent; border: 0px; color: green; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">' and is under GNU General Public License version 2 (GPLv2)</span>
<span style="background-color: transparent; border: 0px; color: green; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">'</span>
<span style="background-color: transparent; border: 0px; color: green; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">' This code contains a helper class exposing property representations</span>
<span style="background-color: transparent; border: 0px; color: green; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">' of the string resources defined in the specified .ResW file</span>
<span style="background-color: transparent; border: 0px; color: green; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">'</span>
<span style="background-color: transparent; border: 0px; color: green; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">' Generated: 11/12/2012 21:30:52</span>
<span style="background-color: transparent; border: 0px; color: green; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">'</auto-generatedInfo></span>
<span style="background-color: transparent; border: 0px; color: green; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">'--------------------------------------------------------------------------------------------------</span>
<span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Namespace</span> AppVb.LocalizedStrings
<span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Partial</span> <span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Public</span> <span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Class</span> Resources
<span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Private</span> <span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Shared</span> resourceLoader <span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">As</span> ResourceLoader = <span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">New</span> ResourceLoader()
<span style="background-color: transparent; border: 0px; color: green; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">'''<summary></span>
<span style="background-color: transparent; border: 0px; color: green; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">'''Localized resource similar to "Test 1 value"</span>
<span style="background-color: transparent; border: 0px; color: green; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">'''</summary></span>
<span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Public</span> <span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Shared</span> <span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">ReadOnly</span> <span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Property</span> Test1() <span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">As</span> <span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">String</span>
<span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Get</span>
<span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Return</span> resourceLoader.GetString(<span style="background-color: transparent; border: 0px; color: #a31515; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">"Test1"</span>)
<span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">End</span> <span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Get</span>
<span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">End</span> <span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Property</span>
<span style="background-color: transparent; border: 0px; color: green; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">'''<summary></span>
<span style="background-color: transparent; border: 0px; color: green; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">'''Localized resource similar to "Test 2 value"</span>
<span style="background-color: transparent; border: 0px; color: green; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">'''</summary></span>
<span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Public</span> <span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Shared</span> <span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">ReadOnly</span> <span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Property</span> Test2() <span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">As</span> <span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">String</span>
<span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Get</span>
<span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Return</span> resourceLoader.GetString(<span style="background-color: transparent; border: 0px; color: #a31515; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">"Test2"</span>)
<span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">End</span> <span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Get</span>
<span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">End</span> <span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Property</span>
<span style="background-color: transparent; border: 0px; color: green; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">'''<summary></span>
<span style="background-color: transparent; border: 0px; color: green; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">'''Localized resource similar to "Test 3 value"</span>
<span style="background-color: transparent; border: 0px; color: green; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">'''</summary></span>
<span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Public</span> <span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Shared</span> <span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">ReadOnly</span> <span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Property</span> Test3() <span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">As</span> <span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">String</span>
<span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Get</span>
<span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Return</span> resourceLoader.GetString(<span style="background-color: transparent; border: 0px; color: #a31515; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">"Test3"</span>)
<span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">End</span> <span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Get</span>
<span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">End</span> <span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Property</span>
<span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">End</span> <span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Class</span>
<span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">End</span> <span style="background-color: transparent; border: 0px; color: blue; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Namespace</span></pre>
</div>
</div>
</div>
Christian Resma Hellehttp://www.blogger.com/profile/16521776612083091477noreply@blogger.com0tag:blogger.com,1999:blog-4995334164049002857.post-45933023735174155182013-01-17T19:38:00.001+01:002013-01-17T19:38:12.442+01:00ParenthoodOnce again I have taken a break from blogging. Parenting and my new family has been my absolute top priority and I've been having a hard time finding the time to write articles. I really enjoy spending time with my son and wife and I take advantage of every possible moment to do so.<br />
<br />
I ended up at a schedule that starts around 5:30 AM in which my son wakes up, and wakes me up. I go and start preparing some breakfast for him. We then have a cozy morning playing around the house. I drop him off at day care as late possible (in my case 9:00 AM) and then drive to the office, or to a customer, or back home if I'm working from home. I pick my son up at between 3:00-4:00 PM and spend time with him and my wife until around 6:30 PM (this is his bed time and I'm very lucky that he has no trouble sleeping). From around 6:30 to 8:00-9:00 PM I spend some time with my wife discussing how our days went and do some planning for the following days. My wife goes to bed a bit early, and when that happens I go back to work. Since I drastically shortened by day, I need to do quite a bit of catching up at night. I usually work an extra 2-3 hours more at night, then I have an hour or 2 to give my mind a rest or work on a hobby project. My day usually ends between 12:30 AM and 2:00 AM. I need at least 4 hours of sleep to recharge for the next day, otherwise I won't be able to last a full week on my schedule.<br />
<br />
Hence the break from blogging :)Christian Resma Hellehttp://www.blogger.com/profile/16521776612083091477noreply@blogger.com0tag:blogger.com,1999:blog-4995334164049002857.post-65750552915520031932012-04-04T22:24:00.001+02:002012-04-04T22:24:42.717+02:00Windows Phone and HTML5 - Danish Developer Conference 2012 Session RecordingHere's the recording of my session on Windows Phone and HTML5 for the Danish Developer Conference 2012, for those who missed it...<br />
<br />
<iframe style="height:288px;width:512px" src="http://channel9.msdn.com/posts/Windows-Phone--HTML5/player?w=512&h=288" frameBorder="0" scrolling="no" ></iframe><br />
<br />
You can also watch it from <a href="http://channel9.msdn.com/posts/Windows-Phone--HTML5">Channel9</a><br />
<br />Christian Resma Hellehttp://www.blogger.com/profile/16521776612083091477noreply@blogger.com1tag:blogger.com,1999:blog-4995334164049002857.post-36929517692546663682012-03-10T00:16:00.000+01:002012-03-10T07:03:55.389+01:00Accessing the Accelerometer from HTML5 and Javascript with Windows Phone 7In my <a href="http://christian-helle.blogspot.com/2012/03/integrating-html5-and-javascript-with.html">previous post</a> I discussed how to have Javascript code hosted in a WebBrowser control execute .NET code in the host application and vice versa. I also demonstrated how to retrieve and display device status information using HTML5 hosted in a WebBrowser control.<br />
<br />
For this sample I would like to demonstrate how to access the <a href="http://msdn.microsoft.com/en-us/library/microsoft.devices.sensors.accelerometer.aspx">Accelerometer</a> sensor from HTML5 and Javascript. To make things more interesting, the Accelerometer reading data will be constantly updated every 100 milliseconds and .NET code will repeatedly call a Javascript method as Accelerometer reading data gets updated<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjRQMkafWH1B5yo_hBWUunMVqDi5_ER3KhJb5dbDKZZ7vNtxoJ5jiTgOPfEaVpxCUp1Tr-1GWdkARdH5y0oJOmIPGWUtzEr4r5fNCfnLQQbfzA6s0np-1wE1CTN8vCxBjf2dcUic9ilYQiu/s1600/AccelerometerEmulator.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjRQMkafWH1B5yo_hBWUunMVqDi5_ER3KhJb5dbDKZZ7vNtxoJ5jiTgOPfEaVpxCUp1Tr-1GWdkARdH5y0oJOmIPGWUtzEr4r5fNCfnLQQbfzA6s0np-1wE1CTN8vCxBjf2dcUic9ilYQiu/s640/AccelerometerEmulator.png" width="336" /></a></div><br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhpQnXtnUtjvK4DK129r7s1x8elx5nEFbisiXSCfzxN54DJvJde1W3daFBcCl7UxtcMVze2rj5qzU9RQQ3xL2zZutkjD1v0NFIUA0ffYx1qXyvpEILGGq7xv1vqg7HxVqCkroXWjtsUfm54/s1600/AccelerometerTool.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="569" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhpQnXtnUtjvK4DK129r7s1x8elx5nEFbisiXSCfzxN54DJvJde1W3daFBcCl7UxtcMVze2rj5qzU9RQQ3xL2zZutkjD1v0NFIUA0ffYx1qXyvpEILGGq7xv1vqg7HxVqCkroXWjtsUfm54/s640/AccelerometerTool.png" width="640" /></a></div><br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
And here's the code...<br />
<br />
<b>Default.html (HTML5 + Javascript)</b><br />
<br />
The code below is going to be used as a local html file that is to be copied to isolated storage. Let's put this in a folder called HTML<br />
<br />
<div style="font-family: Consolas; font-size: 10pt; color: black; background: white;"><p style="margin: 0px;"><span style="color: blue;"><!</span><span style="color: maroon;">DOCTYPE</span> <span style="color: red;">html</span><span style="color: blue;">></span></p><p style="margin: 0px;"><span style="color: blue;"><</span><span style="color: maroon;">html</span><span style="color: blue;">></span></p><p style="margin: 0px;"><span style="color: blue;"><</span><span style="color: maroon;">head</span><span style="color: blue;">></span></p><p style="margin: 0px;"> <span style="color: blue;"><</span><span style="color: maroon;">meta</span> <span style="color: red;">name</span><span style="color: blue;">="viewport"</span> <span style="color: red;">content</span><span style="color: blue;">="width=480, height=800, user-scalable=no"</span> <span style="color: blue;">/></span></p><p style="margin: 0px;"> <span style="color: blue;"><</span><span style="color: maroon;">meta</span> <span style="color: red;">name</span><span style="color: blue;">="MobileOptimized"</span> <span style="color: red;">content</span><span style="color: blue;">="width"</span> <span style="color: blue;">/></span></p><p style="margin: 0px;"> <span style="color: blue;"><</span><span style="color: maroon;">meta</span> <span style="color: red;">name</span><span style="color: blue;">="HandheldFriendly"</span> <span style="color: red;">content</span><span style="color: blue;">="true"</span> <span style="color: blue;">/></span></p><p style="margin: 0px;"> <span style="color: blue;"><</span><span style="color: maroon;">title</span><span style="color: blue;">></span>HTML5 and Windows Phone 7<span style="color: blue;"></</span><span style="color: maroon;">title</span><span style="color: blue;">></span></p><p style="margin: 0px;"> <span style="color: blue;"><</span><span style="color: maroon;">style</span><span style="color: blue;">></span></p><p style="margin: 0px;"> <span style="color: maroon;">body</span></p><p style="margin: 0px;"> {</p><p style="margin: 0px;"> <span style="color: red;">color</span>: <span style="color: blue;">White</span>;</p><p style="margin: 0px;"> <span style="color: red;">background-color</span>: <span style="color: blue;">Black</span>;</p><p style="margin: 0px;"> <span style="color: red;">font-family</span>: <span style="color: blue;">'Segoe WP Semibold'</span>;</p><p style="margin: 0px;"> <span style="color: red;">text-align</span>: <span style="color: blue;">left</span>;</p><p style="margin: 0px;"> }</p><p style="margin: 0px;"> <span style="color: maroon;">h3</span></p><p style="margin: 0px;"> {</p><p style="margin: 0px;"> <span style="color: red;">font-size</span>: <span style="color: blue;">20pt</span>;</p><p style="margin: 0px;"> }</p><p style="margin: 0px;"> <span style="color: maroon;">input</span></p><p style="margin: 0px;"> {</p><p style="margin: 0px;"> <span style="color: red;">color</span>: <span style="color: blue;">#ffffff</span>;</p><p style="margin: 0px;"> <span style="color: red;">background-color</span>: <span style="color: blue;">#000000</span>;</p><p style="margin: 0px;"> <span style="color: red;">border</span>: <span style="color: blue;">2px</span> <span style="color: blue;">solid</span> <span style="color: blue;">white</span>;</p><p style="margin: 0px;"> <span style="color: red;">vertical-align</span>: <span style="color: blue;">baseline</span>;</p><p style="margin: 0px;"> <span style="color: red;">font-size</span>: <span style="color: blue;">17pt</span>;</p><p style="margin: 0px;"> <span style="color: red;">min-width</span>: <span style="color: blue;">40px</span>;</p><p style="margin: 0px;"> <span style="color: red;">min-height</span>: <span style="color: blue;">40px</span>;</p><p style="margin: 0px;"> <span style="color: red;">margin</span>: <span style="color: blue;">5</span>;</p><p style="margin: 0px;"> }</p><p style="margin: 0px;"> <span style="color: blue;"></</span><span style="color: maroon;">style</span><span style="color: blue;">></span></p><p style="margin: 0px;"><span style="color: blue;"></</span><span style="color: maroon;">head</span><span style="color: blue;">></span></p><p style="margin: 0px;"><span style="color: blue;"><</span><span style="color: maroon;">body</span> <span style="color: red;">onload</span><span style="color: blue;">="onLoad()"></span></p><p style="margin: 0px;"> <span style="color: blue;"><</span><span style="color: maroon;">div</span><span style="color: blue;">></span></p><p style="margin: 0px;"> <span style="color: blue;"><</span><span style="color: maroon;">h3</span><span style="color: blue;">></span></p><p style="margin: 0px;"> X:<span style="color: blue;"></</span><span style="color: maroon;">h3</span><span style="color: blue;">></span></p><p style="margin: 0px;"> <span style="color: blue;"><</span><span style="color: maroon;">input</span> <span style="color: red;">id</span><span style="color: blue;">="x"</span> <span style="color: red;">type</span><span style="color: blue;">="text"</span> <span style="color: red;">value</span><span style="color: blue;">="0"</span> <span style="color: blue;">/></span></p><p style="margin: 0px;"> <span style="color: blue;"><</span><span style="color: maroon;">h3</span><span style="color: blue;">></span></p><p style="margin: 0px;"> Y:<span style="color: blue;"></</span><span style="color: maroon;">h3</span><span style="color: blue;">></span></p><p style="margin: 0px;"> <span style="color: blue;"><</span><span style="color: maroon;">input</span> <span style="color: red;">id</span><span style="color: blue;">="y"</span> <span style="color: red;">type</span><span style="color: blue;">="text"</span> <span style="color: red;">value</span><span style="color: blue;">="0"</span> <span style="color: blue;">/></span></p><p style="margin: 0px;"> <span style="color: blue;"><</span><span style="color: maroon;">h3</span><span style="color: blue;">></span></p><p style="margin: 0px;"> Z:<span style="color: blue;"></</span><span style="color: maroon;">h3</span><span style="color: blue;">></span></p><p style="margin: 0px;"> <span style="color: blue;"><</span><span style="color: maroon;">input</span> <span style="color: red;">id</span><span style="color: blue;">="z"</span> <span style="color: red;">type</span><span style="color: blue;">="text"</span> <span style="color: red;">value</span><span style="color: blue;">="0"</span> <span style="color: blue;">/></span></p><p style="margin: 0px;"> <span style="color: blue;"></</span><span style="color: maroon;">div</span><span style="color: blue;">></span></p><p style="margin: 0px;"> <span style="color: blue;"><</span><span style="color: maroon;">script</span> <span style="color: red;">type</span><span style="color: blue;">="text/javascript"></span></p><p style="margin: 0px;"> <span style="color: blue;">function</span> onLoad() {</p><p style="margin: 0px;"> window.external.notify(<span style="color: maroon;">"startAccelerometer"</span>);</p><p style="margin: 0px;"> }</p><p style="margin: 0px;"> </p><p style="margin: 0px;"> <span style="color: blue;">function</span> accelerometerCallback(x, y, z) {</p><p style="margin: 0px;"> document.getElementById(<span style="color: maroon;">"x"</span>).value = x;</p><p style="margin: 0px;"> document.getElementById(<span style="color: maroon;">"y"</span>).value = y;</p><p style="margin: 0px;"> document.getElementById(<span style="color: maroon;">"z"</span>).value = z;</p><p style="margin: 0px;"> }</p><p style="margin: 0px;"> <span style="color: blue;"></</span><span style="color: maroon;">script</span><span style="color: blue;">></span></p><p style="margin: 0px;"><span style="color: blue;"></</span><span style="color: maroon;">body</span><span style="color: blue;">></span></p><p style="margin: 0px;"><span style="color: blue;"></</span><span style="color: maroon;">html</span><span style="color: blue;">></span></p><p style="margin: 0px;"> </p></div><br />
<b>MainPage.xaml</b><br />
<br />
The code below is the main page of the Silverlight application that will host the HTML content<br />
<br />
<div style="background: white; color: black; font-family: Consolas; font-size: 10pt;"><div style="margin: 0px;"><span style="color: blue;"><</span><span style="color: #a31515;">phone</span><span style="color: blue;">:</span><span style="color: #a31515;">PhoneApplicationPage</span><span style="color: red;"> x</span><span style="color: blue;">:</span><span style="color: red;">Class</span><span style="color: blue;">="PhoneApp.MainPage"</span></div><div style="margin: 0px;"> <span style="color: red;"> xmlns</span><span style="color: blue;">="http://schemas.microsoft.com/winfx/2006/xaml/presentation"</span></div><div style="margin: 0px;"> <span style="color: red;"> xmlns</span><span style="color: blue;">:</span><span style="color: red;">x</span><span style="color: blue;">="http://schemas.microsoft.com/winfx/2006/xaml"</span></div><div style="margin: 0px;"> <span style="color: red;"> xmlns</span><span style="color: blue;">:</span><span style="color: red;">phone</span><span style="color: blue;">="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"</span></div><div style="margin: 0px;"> <span style="color: red;"> xmlns</span><span style="color: blue;">:</span><span style="color: red;">shell</span><span style="color: blue;">="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"</span></div><div style="margin: 0px;"> <span style="color: red;"> xmlns</span><span style="color: blue;">:</span><span style="color: red;">d</span><span style="color: blue;">="http://schemas.microsoft.com/expression/blend/2008"</span></div><div style="margin: 0px;"> <span style="color: red;"> xmlns</span><span style="color: blue;">:</span><span style="color: red;">mc</span><span style="color: blue;">="http://schemas.openxmlformats.org/markup-compatibility/2006"</span></div><div style="margin: 0px;"> <span style="color: red;"> mc</span><span style="color: blue;">:</span><span style="color: red;">Ignorable</span><span style="color: blue;">="d"</span></div><div style="margin: 0px;"> <span style="color: red;"> d</span><span style="color: blue;">:</span><span style="color: red;">DesignWidth</span><span style="color: blue;">="480"</span></div><div style="margin: 0px;"> <span style="color: red;"> d</span><span style="color: blue;">:</span><span style="color: red;">DesignHeight</span><span style="color: blue;">="768"</span></div><div style="margin: 0px;"> <span style="color: red;"> FontFamily</span><span style="color: blue;">="{</span><span style="color: #a31515;">StaticResource</span><span style="color: red;"> PhoneFontFamilyNormal</span><span style="color: blue;">}"</span></div><div style="margin: 0px;"> <span style="color: red;"> FontSize</span><span style="color: blue;">="{</span><span style="color: #a31515;">StaticResource</span><span style="color: red;"> PhoneFontSizeNormal</span><span style="color: blue;">}"</span></div><div style="margin: 0px;"> <span style="color: red;"> Foreground</span><span style="color: blue;">="{</span><span style="color: #a31515;">StaticResource</span><span style="color: red;"> PhoneForegroundBrush</span><span style="color: blue;">}"</span></div><div style="margin: 0px;"> <span style="color: red;"> SupportedOrientations</span><span style="color: blue;">="Portrait"</span></div><div style="margin: 0px;"> <span style="color: red;"> Orientation</span><span style="color: blue;">="Portrait"</span></div><div style="margin: 0px;"> <span style="color: red;"> shell</span><span style="color: blue;">:</span><span style="color: red;">SystemTray.IsVisible</span><span style="color: blue;">="True"</span></div><div style="margin: 0px;"> <span style="color: red;"> Loaded</span><span style="color: blue;">="PhoneApplicationPage_Loaded"></span></div><div style="margin: 0px;"><br />
</div><div style="margin: 0px;"><span style="color: #a31515;"> </span><span style="color: blue;"><</span><span style="color: #a31515;">Grid</span><span style="color: red;"> x</span><span style="color: blue;">:</span><span style="color: red;">Name</span><span style="color: blue;">="LayoutRoot"</span></div><div style="margin: 0px;"> <span style="color: red;"> Background</span><span style="color: blue;">="Transparent"></span></div><div style="margin: 0px;"><span style="color: #a31515;"> </span><span style="color: blue;"><</span><span style="color: #a31515;">phone</span><span style="color: blue;">:</span><span style="color: #a31515;">WebBrowser</span><span style="color: red;"> Name</span><span style="color: blue;">="browser"</span></div><div style="margin: 0px;"> <span style="color: red;"> IsScriptEnabled</span><span style="color: blue;">="True"</span></div><div style="margin: 0px;"> <span style="color: red;"> Source</span><span style="color: blue;">="HTML/Default.html"</span></div><div style="margin: 0px;"> <span style="color: red;"> ScriptNotify</span><span style="color: blue;">="browser_ScriptNotify" /></span></div><div style="margin: 0px;"><span style="color: #a31515;"> </span><span style="color: blue;"></</span><span style="color: #a31515;">Grid</span><span style="color: blue;">></span></div><div style="margin: 0px;"><br />
</div><div style="margin: 0px;"><span style="color: blue;"></</span><span style="color: #a31515;">phone</span><span style="color: blue;">:</span><span style="color: #a31515;">PhoneApplicationPage</span><span style="color: blue;">></span></div></div><br />
<b>MainPage.xaml.cs</b><br />
<br />
And here's the code behind the xaml file<br />
<br />
<div style="font-family: Consolas; font-size: 10pt; color: black; background: white;"><p style="margin: 0px;"><span style="color: blue;">public</span> <span style="color: blue;">partial</span> <span style="color: blue;">class</span> <span style="color: #2b91af;">MainPage</span> : <span style="color: #2b91af;">PhoneApplicationPage</span></p><p style="margin: 0px;">{</p><p style="margin: 0px;"> <span style="color: blue;">private</span> Microsoft.Devices.Sensors.<span style="color: #2b91af;">Accelerometer</span> accelerometer;</p><p style="margin: 0px;"> </p><p style="margin: 0px;"> <span style="color: blue;">public</span> MainPage()</p><p style="margin: 0px;"> {</p><p style="margin: 0px;"> InitializeComponent();</p><p style="margin: 0px;"> }</p><p style="margin: 0px;"> </p><p style="margin: 0px;"> <span style="color: blue;">private</span> <span style="color: blue;">void</span> PhoneApplicationPage_Loaded(<span style="color: blue;">object</span> sender, <span style="color: #2b91af;">RoutedEventArgs</span> e)</p><p style="margin: 0px;"> {</p><p style="margin: 0px;"> <span style="color: blue;">using</span> (<span style="color: #2b91af;">IsolatedStorageFile</span> store = <span style="color: #2b91af;">IsolatedStorageFile</span>.GetUserStoreForApplication())</p><p style="margin: 0px;"> {</p><p style="margin: 0px;"> <span style="color: blue;">if</span> (!store.DirectoryExists(<span style="color: #a31515;">"HTML"</span>)) store.CreateDirectory(<span style="color: #a31515;">"HTML"</span>);</p><p style="margin: 0px;"> CopyToIsolatedStorage(<span style="color: #a31515;">"HTML\\Default.html"</span>, store);</p><p style="margin: 0px;"> }</p><p style="margin: 0px;"> }</p><p style="margin: 0px;"> </p><p style="margin: 0px;"> <span style="color: blue;">private</span> <span style="color: blue;">static</span> <span style="color: blue;">void</span> CopyToIsolatedStorage(<span style="color: blue;">string</span> file, <span style="color: #2b91af;">IsolatedStorageFile</span> store, <span style="color: blue;">bool</span> overwrite = <span style="color: blue;">true</span>)</p><p style="margin: 0px;"> {</p><p style="margin: 0px;"> <span style="color: blue;">if</span> (store.FileExists(file) && !overwrite)</p><p style="margin: 0px;"> <span style="color: blue;">return</span>;</p><p style="margin: 0px;"> </p><p style="margin: 0px;"> <span style="color: blue;">using</span> (<span style="color: #2b91af;">Stream</span> resourceStream = <span style="color: #2b91af;">Application</span>.GetResourceStream(<span style="color: blue;">new</span> <span style="color: #2b91af;">Uri</span>(file, <span style="color: #2b91af;">UriKind</span>.Relative)).Stream)</p><p style="margin: 0px;"> <span style="color: blue;">using</span> (<span style="color: #2b91af;">IsolatedStorageFileStream</span> fileStream = store.OpenFile(file, <span style="color: #2b91af;">FileMode</span>.Create, <span style="color: #2b91af;">FileAccess</span>.ReadWrite, <span style="color: #2b91af;">FileShare</span>.ReadWrite))</p><p style="margin: 0px;"> {</p><p style="margin: 0px;"> <span style="color: blue;">int</span> bytesRead;</p><p style="margin: 0px;"> <span style="color: blue;">var</span> buffer = <span style="color: blue;">new</span> <span style="color: blue;">byte</span>[resourceStream.Length];</p><p style="margin: 0px;"> <span style="color: blue;">while</span> ((bytesRead = resourceStream.Read(buffer, 0, buffer.Length)) > 0)</p><p style="margin: 0px;"> fileStream.Write(buffer, 0, bytesRead);</p><p style="margin: 0px;"> }</p><p style="margin: 0px;"> }</p><p style="margin: 0px;"> </p><p style="margin: 0px;"> <span style="color: blue;">private</span> <span style="color: blue;">void</span> browser_ScriptNotify(<span style="color: blue;">object</span> sender, <span style="color: #2b91af;">NotifyEventArgs</span> e)</p><p style="margin: 0px;"> {</p><p style="margin: 0px;"> <span style="color: blue;">if</span> (e.Value == <span style="color: #a31515;">"startAccelerometer"</span>)</p><p style="margin: 0px;"> {</p><p style="margin: 0px;"> <span style="color: blue;">if</span> (accelerometer == <span style="color: blue;">null</span>)</p><p style="margin: 0px;"> {</p><p style="margin: 0px;"> accelerometer = <span style="color: blue;">new</span> Microsoft.Devices.Sensors.<span style="color: #2b91af;">Accelerometer</span> { TimeBetweenUpdates = <span style="color: #2b91af;">TimeSpan</span>.FromMilliseconds(100) };</p><p style="margin: 0px;"> accelerometer.CurrentValueChanged += (o, args) => Dispatcher.BeginInvoke(() =></p><p style="margin: 0px;"> {</p><p style="margin: 0px;"> <span style="color: blue;">var</span> x = args.SensorReading.Acceleration.X.ToString(<span style="color: #a31515;">"0.000"</span>);</p><p style="margin: 0px;"> <span style="color: blue;">var</span> y = args.SensorReading.Acceleration.Y.ToString(<span style="color: #a31515;">"0.000"</span>);</p><p style="margin: 0px;"> <span style="color: blue;">var</span> z = args.SensorReading.Acceleration.Z.ToString(<span style="color: #a31515;">"0.000"</span>);</p><p style="margin: 0px;"> </p><p style="margin: 0px;"> browser.InvokeScript(<span style="color: #a31515;">"eval"</span>, <span style="color: blue;">string</span>.Format(<span style="color: #a31515;">"accelerometerCallback(</span><span style="color: #3cb371;">{0}</span><span style="color: #a31515;">,</span><span style="color: #3cb371;">{1}</span><span style="color: #a31515;">,</span><span style="color: #3cb371;">{2}</span><span style="color: #a31515;">)"</span>, x, y, z));</p><p style="margin: 0px;"> });</p><p style="margin: 0px;"> accelerometer.Start();</p><p style="margin: 0px;"> }</p><p style="margin: 0px;"> }</p><p style="margin: 0px;"> }</p><p style="margin: 0px;">}</p></div><br />
What happens in the code above is that a Javascript method is executed that notifies the host application telling it to start the Accelerometer when the HTML has loaded. We then add an event handler to the Accelerometers <a href="http://msdn.microsoft.com/en-us/library/hh239103.aspx">CurrentValueChanged</a> event that invokes the accelerometerCallback Javascript method and passing in Accelerometer reading data as the arguments. Notice that I use <b>eval</b> as the Javascript method to invoke and passing the method call as an argument, this is because the accelerometer reading data is retrieved on a worker thread and for some reason an unknown system error occurs even when executing code on the UI thread through the Page Dispatcher.BeginInvoke() method. I figured out that using <b>eval</b> was the only way to execute Javascript code from a .NET worker thread.<br />
<br />
I hope you found this useful. You can grab the full source code for the example here:<br />
<iframe title ="Preview" scrolling="no" marginheight="0" marginwidth="0" frameborder="0" width="98px" height="120px" style="padding:0;background-color:#fcfcfc;" src="https://skydrive.live.com/embed?cid=CA531E7FB4762C70&resid=CA531E7FB4762C70%21847&authkey=ANDLSxn_XMFkZCU"></iframe>Christian Resma Hellehttp://www.blogger.com/profile/16521776612083091477noreply@blogger.com3tag:blogger.com,1999:blog-4995334164049002857.post-29723433042651970732012-03-08T22:57:00.001+01:002012-03-09T23:29:57.513+01:00Integrating HTML5 and Javascript with Windows Phone 7Everyone, everywhere is talking about HTML5 these days. I myself did a recent talk at the <a href="http://christian-helle.blogspot.com/2012/03/html5-and-windows-phone-7.html">Danish Developer Conference 2012 on Windows Phone and HTML5</a>. I get the point and I see the power and beauty of HTML5. But, HTML5 is as far as I can see not entirely ready yet and as for mobile applications, I would always choose writing a native application that takes full advantage of the platform and not just an application that runs in a browser, even if the the browser component is hosted in a native application. I think developers should really learn to appreciate the platform more.<br />
<br />
In this article I would like to explain how to integrate HTML5 + Javascript in a Windows Phone application and the same demonstrate how to call a .NET method from Javascript and how to call a Javascript method from .NET<br />
<br />
So here's what we need to do to get started:<br />
<ol><li>Create a Windows Phone Silverlight application</li>
<li>Add a WebBrowser component on the main page</li>
<li>Set the <b>IsScriptEnabled </b>property of the WebBrowser component to <b>true</b></li>
<li>Add an event handler to the <b>ScriptNotify </b>event of the WebBrowser component</li>
<li>Create a folder on the project called HTML and add the HTML, Javascript, and Stylesheet assets to this folder</li>
<li>Write code to copy the HTML related assets to IsolatedStorage</li>
<li>Set the source of the WebBrowser component to the main HTML page</li>
</ol><div>Simple isn't it?<br />
<br />
<br />
<b>How it works</b><br />
<br />
The steps above really do seem to be quite simple, and yes it really is. For Javascript to call into the host of the WebBrowser control we can use the <b>window.external.notify()</b> method. This is the same approach for having Javascript code execute code in the host application in other platforms. The <b>window.external.notify()</b> method takes a string which can be used to contain meta data that describes what you want the host to do. And for .NET code to execute Javascript code we use the <b>InvokeScript()</b> method of the WebBrowser control. The <b>InvokeScript()</b> method takes a string parameter that describes the Javascript method to execute, and a collection of strings that describe the arguments to be passed to the Javascript method to execute. If the method that will invoke a javascript function from the host is running on a non-UI thread (worker thread) then the best approach to using this method is by calling <b>InvokeScript("eval", "methodName(args1,args2,args3)")</b> instead of passing the name of the method to be invoked as the first method argument.<br />
<br />
Here's a diagram I used in DDC 2012 that illustrates the process mentioned above:<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWVZh526Fj01y9HyvQ8t2VTTfTM2Iy-bckT7tJ7BZnfKkjFo2tN4OIbbRI2qNEatWI88UfIQtwjUazjCs3AuYmJISdGMTvo5DhvAyFALFubKmqYYFMNuu3Y4AlG4Sqg3aRn_Lu0hcjur8a/s1600/JavascriptCSharpInterop.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="408" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWVZh526Fj01y9HyvQ8t2VTTfTM2Iy-bckT7tJ7BZnfKkjFo2tN4OIbbRI2qNEatWI88UfIQtwjUazjCs3AuYmJISdGMTvo5DhvAyFALFubKmqYYFMNuu3Y4AlG4Sqg3aRn_Lu0hcjur8a/s640/JavascriptCSharpInterop.jpg" width="640" /></a></div><br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
For this example, we will have an application that hosts a HTML5 page that displays memory information of the device (as shown in the screenshot below)<br />
<br />
<div class="separator" style="clear: both; text-align: center;"></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhuc5eHVD1W0rBmEPsug0VIwLINzpg7S_48rGf_8EJ_oWSJOt9lcUJ4EwK1a6ND2EUs6OJC-5-RvUV63dC41FJzwsXp_b42ZCHXBh8L-X1NhmsmoVjWvpmbUaMhVco-H_ld0lbb06Q0giQX/s1600/HTML_WP7.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhuc5eHVD1W0rBmEPsug0VIwLINzpg7S_48rGf_8EJ_oWSJOt9lcUJ4EwK1a6ND2EUs6OJC-5-RvUV63dC41FJzwsXp_b42ZCHXBh8L-X1NhmsmoVjWvpmbUaMhVco-H_ld0lbb06Q0giQX/s640/HTML_WP7.png" width="337" /></a></div><br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
And here's the code...<br />
<br />
<br />
<b>Default.html (HTML5 + Javascript)</b><br />
<br />
The code below is going to be used as a local html file that is to be copied to isolated storage. Let's put this in a folder called HTML<br />
<br />
<div style="background: white; color: black; font-family: Consolas; font-size: 10pt;"><div style="margin: 0px;"><span style="color: blue;"><!</span><span style="color: maroon;">DOCTYPE</span> <span style="color: red;">html</span><span style="color: blue;">></span></div><div style="margin: 0px;"><span style="color: blue;"><</span><span style="color: maroon;">html</span><span style="color: blue;">></span></div><div style="margin: 0px;"><span style="color: blue;"><</span><span style="color: maroon;">head</span><span style="color: blue;">></span></div><div style="margin: 0px;"> <span style="color: blue;"><</span><span style="color: maroon;">meta</span> <span style="color: red;">name</span><span style="color: blue;">="viewport"</span> <span style="color: red;">content</span><span style="color: blue;">="width=480, height=800, user-scalable=no"</span> <span style="color: blue;">/></span></div><div style="margin: 0px;"> <span style="color: blue;"><</span><span style="color: maroon;">meta</span> <span style="color: red;">name</span><span style="color: blue;">="MobileOptimized"</span> <span style="color: red;">content</span><span style="color: blue;">="width"</span> <span style="color: blue;">/></span></div><div style="margin: 0px;"> <span style="color: blue;"><</span><span style="color: maroon;">meta</span> <span style="color: red;">name</span><span style="color: blue;">="HandheldFriendly"</span> <span style="color: red;">content</span><span style="color: blue;">="true"</span> <span style="color: blue;">/></span></div><div style="margin: 0px;"> <span style="color: blue;"><</span><span style="color: maroon;">title</span><span style="color: blue;">></span>HTML5 and Windows Phone 7<span style="color: blue;"></</span><span style="color: maroon;">title</span><span style="color: blue;">></span></div><div style="margin: 0px;"> <span style="color: blue;"><</span><span style="color: maroon;">style</span><span style="color: blue;">></span></div><div style="margin: 0px;"> <span style="color: maroon;">body</span></div><div style="margin: 0px;"> {</div><div style="margin: 0px;"> <span style="color: red;">color</span>: <span style="color: blue;">White</span>;</div><div style="margin: 0px;"> <span style="color: red;">background-color</span>: <span style="color: blue;">Black</span>;</div><div style="margin: 0px;"> <span style="color: red;">font-family</span>: <span style="color: blue;">'Segoe WP Semibold'</span>;</div><div style="margin: 0px;"> <span style="color: red;">text-align</span>: <span style="color: blue;">left</span>;</div><div style="margin: 0px;"> }</div><div style="margin: 0px;"> <span style="color: maroon;">h3</span></div><div style="margin: 0px;"> {</div><div style="margin: 0px;"> <span style="color: red;">font-size</span>: <span style="color: blue;">20pt</span>;</div><div style="margin: 0px;"> }</div><div style="margin: 0px;"> <span style="color: maroon;">input</span></div><div style="margin: 0px;"> {</div><div style="margin: 0px;"> <span style="color: red;">color</span>: <span style="color: blue;">#ffffff</span>;</div><div style="margin: 0px;"> <span style="color: red;">background-color</span>: <span style="color: blue;">#000000</span>;</div><div style="margin: 0px;"> <span style="color: red;">border</span>: <span style="color: blue;">2px</span> <span style="color: blue;">solid</span> <span style="color: blue;">white</span>;</div><div style="margin: 0px;"> <span style="color: red;">vertical-align</span>: <span style="color: blue;">baseline</span>;</div><div style="margin: 0px;"> <span style="color: red;">font-size</span>: <span style="color: blue;">17pt</span>;</div><div style="margin: 0px;"> <span style="color: red;">min-width</span>: <span style="color: blue;">40px</span>;</div><div style="margin: 0px;"> <span style="color: red;">min-height</span>: <span style="color: blue;">40px</span>;</div><div style="margin: 0px;"> <span style="color: red;">margin</span>: <span style="color: blue;">5</span>;</div><div style="margin: 0px;"> }</div><div style="margin: 0px;"> <span style="color: blue;"></</span><span style="color: maroon;">style</span><span style="color: blue;">></span></div><div style="margin: 0px;"><span style="color: blue;"></</span><span style="color: maroon;">head</span><span style="color: blue;">></span></div><div style="margin: 0px;"><span style="color: blue;"><</span><span style="color: maroon;">body</span> <span style="color: red;">onload</span><span style="color: blue;">="onLoad()"></span></div><div style="margin: 0px;"> <span style="color: blue;"><</span><span style="color: maroon;">div</span><span style="color: blue;">></span></div><div style="margin: 0px;"> <span style="color: blue;"><</span><span style="color: maroon;">h3</span><span style="color: blue;">></span></div><div style="margin: 0px;"> Current memory usage:<span style="color: blue;"></</span><span style="color: maroon;">h3</span><span style="color: blue;">></span></div><div style="margin: 0px;"> <span style="color: blue;"><</span><span style="color: maroon;">input</span> <span style="color: red;">id</span><span style="color: blue;">="memoryUsage"</span> <span style="color: red;">type</span><span style="color: blue;">="text"</span> <span style="color: red;">value</span><span style="color: blue;">="0"</span> <span style="color: blue;">/></span></div><div style="margin: 0px;"> <span style="color: blue;"><</span><span style="color: maroon;">h3</span><span style="color: blue;">></span></div><div style="margin: 0px;"> Memory usage limit:<span style="color: blue;"></</span><span style="color: maroon;">h3</span><span style="color: blue;">></span></div><div style="margin: 0px;"> <span style="color: blue;"><</span><span style="color: maroon;">input</span> <span style="color: red;">id</span><span style="color: blue;">="memoryUsageLimit"</span> <span style="color: red;">type</span><span style="color: blue;">="text"</span> <span style="color: red;">value</span><span style="color: blue;">="0"</span> <span style="color: blue;">/></span></div><div style="margin: 0px;"> <span style="color: blue;"><</span><span style="color: maroon;">h3</span><span style="color: blue;">></span></div><div style="margin: 0px;"> Peak memory usage:<span style="color: blue;"></</span><span style="color: maroon;">h3</span><span style="color: blue;">></span></div><div style="margin: 0px;"> <span style="color: blue;"><</span><span style="color: maroon;">input</span> <span style="color: red;">id</span><span style="color: blue;">="peakMemoryUsage"</span> <span style="color: red;">type</span><span style="color: blue;">="text"</span> <span style="color: red;">value</span><span style="color: blue;">="0"</span> <span style="color: blue;">/></span></div><div style="margin: 0px;"> <span style="color: blue;"><</span><span style="color: maroon;">h3</span><span style="color: blue;">></span></div><div style="margin: 0px;"> Total memory:<span style="color: blue;"></</span><span style="color: maroon;">h3</span><span style="color: blue;">></span></div><div style="margin: 0px;"> <span style="color: blue;"><</span><span style="color: maroon;">input</span> <span style="color: red;">id</span><span style="color: blue;">="totalMemory"</span> <span style="color: red;">type</span><span style="color: blue;">="text"</span> <span style="color: red;">value</span><span style="color: blue;">="0"</span> <span style="color: blue;">/></span></div><div style="margin: 0px;"> <span style="color: blue;"></</span><span style="color: maroon;">div</span><span style="color: blue;">></span></div><div style="margin: 0px;"> <span style="color: blue;"><</span><span style="color: maroon;">script</span> <span style="color: red;">type</span><span style="color: blue;">="text/javascript"></span></div><div style="margin: 0px;"> <span style="color: blue;">function</span> onLoad() {</div><div style="margin: 0px;"> window.external.notify(<span style="color: maroon;">"getMemoryUsage"</span>);</div><div style="margin: 0px;"> }</div><div style="margin: 0px;"><br />
</div><div style="margin: 0px;"> <span style="color: blue;">function</span> getMemoryUsageCallback(memoryUsage, memoryUsageLimit, peakMemoryUsage, totalMemory) {</div><div style="margin: 0px;"> document.getElementById(<span style="color: maroon;">"memoryUsage"</span>).value = memoryUsage;</div><div style="margin: 0px;"> document.getElementById(<span style="color: maroon;">"memoryUsageLimit"</span>).value = memoryUsageLimit;</div><div style="margin: 0px;"> document.getElementById(<span style="color: maroon;">"peakMemoryUsage"</span>).value = peakMemoryUsage;</div><div style="margin: 0px;"> document.getElementById(<span style="color: maroon;">"totalMemory"</span>).value = totalMemory;</div><div style="margin: 0px;"> }</div><div style="margin: 0px;"> <span style="color: blue;"></</span><span style="color: maroon;">script</span><span style="color: blue;">></span></div><div style="margin: 0px;"><span style="color: blue;"></</span><span style="color: maroon;">body</span><span style="color: blue;">></span></div><div style="margin: 0px;"><span style="color: blue;"></</span><span style="color: maroon;">html</span><span style="color: blue;">></span></div><div style="margin: 0px;"><br />
</div></div><br />
<b>MainPage.xaml</b><br />
<br />
The code below is the main page of the Silverlight application that will host the HTML content<br />
<br />
<div style="background: white; color: black; font-family: Consolas; font-size: 10pt;"><div style="margin: 0px;"><span style="color: blue;"><</span><span style="color: #a31515;">phone</span><span style="color: blue;">:</span><span style="color: #a31515;">PhoneApplicationPage</span><span style="color: red;"> x</span><span style="color: blue;">:</span><span style="color: red;">Class</span><span style="color: blue;">="PhoneApp.MainPage"</span></div><div style="margin: 0px;"> <span style="color: red;"> xmlns</span><span style="color: blue;">="http://schemas.microsoft.com/winfx/2006/xaml/presentation"</span></div><div style="margin: 0px;"> <span style="color: red;"> xmlns</span><span style="color: blue;">:</span><span style="color: red;">x</span><span style="color: blue;">="http://schemas.microsoft.com/winfx/2006/xaml"</span></div><div style="margin: 0px;"> <span style="color: red;"> xmlns</span><span style="color: blue;">:</span><span style="color: red;">phone</span><span style="color: blue;">="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"</span></div><div style="margin: 0px;"> <span style="color: red;"> xmlns</span><span style="color: blue;">:</span><span style="color: red;">shell</span><span style="color: blue;">="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"</span></div><div style="margin: 0px;"> <span style="color: red;"> xmlns</span><span style="color: blue;">:</span><span style="color: red;">d</span><span style="color: blue;">="http://schemas.microsoft.com/expression/blend/2008"</span></div><div style="margin: 0px;"> <span style="color: red;"> xmlns</span><span style="color: blue;">:</span><span style="color: red;">mc</span><span style="color: blue;">="http://schemas.openxmlformats.org/markup-compatibility/2006"</span></div><div style="margin: 0px;"> <span style="color: red;"> mc</span><span style="color: blue;">:</span><span style="color: red;">Ignorable</span><span style="color: blue;">="d"</span></div><div style="margin: 0px;"> <span style="color: red;"> d</span><span style="color: blue;">:</span><span style="color: red;">DesignWidth</span><span style="color: blue;">="480"</span></div><div style="margin: 0px;"> <span style="color: red;"> d</span><span style="color: blue;">:</span><span style="color: red;">DesignHeight</span><span style="color: blue;">="768"</span></div><div style="margin: 0px;"> <span style="color: red;"> FontFamily</span><span style="color: blue;">="{</span><span style="color: #a31515;">StaticResource</span><span style="color: red;"> PhoneFontFamilyNormal</span><span style="color: blue;">}"</span></div><div style="margin: 0px;"> <span style="color: red;"> FontSize</span><span style="color: blue;">="{</span><span style="color: #a31515;">StaticResource</span><span style="color: red;"> PhoneFontSizeNormal</span><span style="color: blue;">}"</span></div><div style="margin: 0px;"> <span style="color: red;"> Foreground</span><span style="color: blue;">="{</span><span style="color: #a31515;">StaticResource</span><span style="color: red;"> PhoneForegroundBrush</span><span style="color: blue;">}"</span></div><div style="margin: 0px;"> <span style="color: red;"> SupportedOrientations</span><span style="color: blue;">="Portrait"</span></div><div style="margin: 0px;"> <span style="color: red;"> Orientation</span><span style="color: blue;">="Portrait"</span></div><div style="margin: 0px;"> <span style="color: red;"> shell</span><span style="color: blue;">:</span><span style="color: red;">SystemTray.IsVisible</span><span style="color: blue;">="True"</span></div><div style="margin: 0px;"> <span style="color: red;"> Loaded</span><span style="color: blue;">="PhoneApplicationPage_Loaded"></span></div><div style="margin: 0px;"><br />
</div><div style="margin: 0px;"><span style="color: #a31515;"> </span><span style="color: blue;"><</span><span style="color: #a31515;">Grid</span><span style="color: red;"> x</span><span style="color: blue;">:</span><span style="color: red;">Name</span><span style="color: blue;">="LayoutRoot"</span></div><div style="margin: 0px;"> <span style="color: red;"> Background</span><span style="color: blue;">="Transparent"></span></div><div style="margin: 0px;"><span style="color: #a31515;"> </span><span style="color: blue;"><</span><span style="color: #a31515;">phone</span><span style="color: blue;">:</span><span style="color: #a31515;">WebBrowser</span><span style="color: red;"> Name</span><span style="color: blue;">="browser"</span></div><div style="margin: 0px;"> <span style="color: red;"> IsScriptEnabled</span><span style="color: blue;">="True"</span></div><div style="margin: 0px;"> <span style="color: red;"> Source</span><span style="color: blue;">="HTML/Default.html"</span></div><div style="margin: 0px;"> <span style="color: red;"> ScriptNotify</span><span style="color: blue;">="browser_ScriptNotify" /></span></div><div style="margin: 0px;"><span style="color: #a31515;"> </span><span style="color: blue;"></</span><span style="color: #a31515;">Grid</span><span style="color: blue;">></span></div><div style="margin: 0px;"><br />
</div><div style="margin: 0px;"><span style="color: blue;"></</span><span style="color: #a31515;">phone</span><span style="color: blue;">:</span><span style="color: #a31515;">PhoneApplicationPage</span><span style="color: blue;">></span></div></div><br />
<br />
<b>MainPage.xaml.cs</b><br />
<br />
And here's the code behind the xaml file<br />
<br />
<div style="background: white; color: black; font-family: Consolas; font-size: 10pt;"><div style="margin: 0px;"><span style="color: blue;">public</span> <span style="color: blue;">partial</span> <span style="color: blue;">class</span> <span style="color: #2b91af;">MainPage</span> : <span style="color: #2b91af;">PhoneApplicationPage</span></div><div style="margin: 0px;">{</div><div style="margin: 0px;"> <span style="color: blue;">public</span> MainPage()</div><div style="margin: 0px;"> {</div><div style="margin: 0px;"> InitializeComponent();</div><div style="margin: 0px;"> }</div><div style="margin: 0px;"><br />
</div><div style="margin: 0px;"> <span style="color: blue;">private</span> <span style="color: blue;">void</span> PhoneApplicationPage_Loaded(<span style="color: blue;">object</span> sender, <span style="color: #2b91af;">RoutedEventArgs</span> e)</div><div style="margin: 0px;"> {</div><div style="margin: 0px;"> <span style="color: blue;">using</span> (<span style="color: #2b91af;">IsolatedStorageFile</span> store = <span style="color: #2b91af;">IsolatedStorageFile</span>.GetUserStoreForApplication())</div><div style="margin: 0px;"> {</div><div style="margin: 0px;"> <span style="color: blue;">if</span> (!store.DirectoryExists(<span style="color: #a31515;">"HTML"</span>)) store.CreateDirectory(<span style="color: #a31515;">"HTML"</span>);</div><div style="margin: 0px;"> CopyToIsolatedStorage(<span style="color: #a31515;">"HTML\\Default.html"</span>, store);</div><div style="margin: 0px;"> }</div><div style="margin: 0px;"> }</div><div style="margin: 0px;"><br />
</div><div style="margin: 0px;"> <span style="color: blue;">private</span> <span style="color: blue;">static</span> <span style="color: blue;">void</span> CopyToIsolatedStorage(<span style="color: blue;">string</span> file, <span style="color: #2b91af;">IsolatedStorageFile</span> store, <span style="color: blue;">bool</span> overwrite = <span style="color: blue;">true</span>)</div><div style="margin: 0px;"> {</div><div style="margin: 0px;"> <span style="color: blue;">if</span> (store.FileExists(file) && !overwrite)</div><div style="margin: 0px;"> <span style="color: blue;">return</span>;</div><div style="margin: 0px;"><br />
</div><div style="margin: 0px;"> <span style="color: blue;">using</span> (<span style="color: #2b91af;">Stream</span> resourceStream = <span style="color: #2b91af;">Application</span>.GetResourceStream(<span style="color: blue;">new</span> <span style="color: #2b91af;">Uri</span>(file, <span style="color: #2b91af;">UriKind</span>.Relative)).Stream)</div><div style="margin: 0px;"> <span style="color: blue;">using</span> (<span style="color: #2b91af;">IsolatedStorageFileStream</span> fileStream = store.OpenFile(file, <span style="color: #2b91af;">FileMode</span>.Create, <span style="color: #2b91af;">FileAccess</span>.ReadWrite, <span style="color: #2b91af;">FileShare</span>.ReadWrite))</div><div style="margin: 0px;"> {</div><div style="margin: 0px;"> <span style="color: blue;">int</span> bytesRead;</div><div style="margin: 0px;"> <span style="color: blue;">var</span> buffer = <span style="color: blue;">new</span> <span style="color: blue;">byte</span>[resourceStream.Length];</div><div style="margin: 0px;"> <span style="color: blue;">while</span> ((bytesRead = resourceStream.Read(buffer, 0, buffer.Length)) > 0)</div><div style="margin: 0px;"> fileStream.Write(buffer, 0, bytesRead);</div><div style="margin: 0px;"> }</div><div style="margin: 0px;"> }</div><div style="margin: 0px;"><br />
</div><div style="margin: 0px;"> <span style="color: blue;">private</span> <span style="color: blue;">void</span> browser_ScriptNotify(<span style="color: blue;">object</span> sender, <span style="color: #2b91af;">NotifyEventArgs</span> e)</div><div style="margin: 0px;"> {</div><div style="margin: 0px;"> <span style="color: blue;">var</span> response = <span style="color: blue;">new</span> <span style="color: blue;">object</span>[]</div><div style="margin: 0px;"> {</div><div style="margin: 0px;"> <span style="color: #2b91af;">DeviceStatus</span>.ApplicationCurrentMemoryUsage, </div><div style="margin: 0px;"> <span style="color: #2b91af;">DeviceStatus</span>.ApplicationMemoryUsageLimit, </div><div style="margin: 0px;"> <span style="color: #2b91af;">DeviceStatus</span>.ApplicationPeakMemoryUsage,</div><div style="margin: 0px;"> <span style="color: #2b91af;">DeviceStatus</span>.DeviceTotalMemory</div><div style="margin: 0px;"> };</div><div style="margin: 0px;"> browser.InvokeScript(<span style="color: #a31515;">"getMemoryUsageCallback"</span>, response.Select(c => c.ToString()).ToArray());</div><div style="margin: 0px;"> }</div><div style="margin: 0px;">}</div></div><br />
What happens in the code above is that when the main page has loaded, the html assets are copied to isolated storage and loaded into the web browser component as a local file. When <a href="http://msdn.microsoft.com/en-us/library/microsoft.phone.controls.webbrowser.scriptnotify(v=vs.92).aspx">ScriptNotify</a> is triggered, the Silverlight application retrieves memory information using the <a href="http://msdn.microsoft.com/en-us/library/ff941122(v=vs.92).aspx">DeviceStatus</a> class and passes this information back to the WebBrowser component by invoking the getMemoryUsageCallback() method using the <a href="http://msdn.microsoft.com/en-us/library/ff402855(v=vs.92).aspx">InvokeScript()</a> method of the WebBrowser component<br />
<br />
The sample above is a very basic and naive but it demonstrates something that can provide endless platform interop possibilities. I hope you found this useful.</div><br />
You can grab the full source code the sample above here:<br />
<iframe title ="Preview" scrolling="no" marginheight="0" marginwidth="0" frameborder="0" width="98px" height="120px" style="padding:0;background-color:#fcfcfc;" src="https://skydrive.live.com/embed?cid=CA531E7FB4762C70&resid=CA531E7FB4762C70%21846&authkey=AIlgEO7SWk3fIeY"></iframe>Christian Resma Hellehttp://www.blogger.com/profile/16521776612083091477noreply@blogger.com6tag:blogger.com,1999:blog-4995334164049002857.post-75885124850773353962012-03-05T22:56:00.000+01:002019-06-11T18:56:25.192+02:00HTML5 and Windows Phone 7Last week I did a talk on HTML5 and Windows Phone for the Danish Developer Conference 2012. The talk was quite successful and around 80% of said that they learned something new, which is the whole point of these conferences.<br />
<br />
If you're interested in my presentation and code examples then you can download it at <a href="http://dl.dropbox.com/u/18352048/Presentations/Windows%20Phone%20and%20HTML5/Windows%20Phone%20and%20HTML5.rar">http://dl.dropbox.com/u/18352048/Presentations/Windows%20Phone%20and%20HTML5/Windows%20Phone%20and%20HTML5.rar</a><br />
<br />
<br />
Christian Resma Hellehttp://www.blogger.com/profile/16521776612083091477noreply@blogger.com0tag:blogger.com,1999:blog-4995334164049002857.post-81684268524095351822012-02-20T22:44:00.000+01:002012-02-20T22:44:13.255+01:00Danish Developer Conference 2012There's a lot of talks about HTML5 these days and I myself will be doing a talk regarding the subject in the Danish Developer Conference. I was planning on saving my content for my presentation but once my talk is done I'll be posting a couple of articles on HTML5 and Windows Phone 7.<br />
<br />
<br />
Here's an introduction / teaser to what I'll be presenting...<br />
<br />
<iframe allowfullscreen="" frameborder="0" height="480" src="http://www.youtube.com/embed/Hxctd7Dc9TQ" width="640"></iframe><br />Christian Resma Hellehttp://www.blogger.com/profile/16521776612083091477noreply@blogger.com0tag:blogger.com,1999:blog-4995334164049002857.post-54528953626231563652012-02-08T09:50:00.001+01:002013-01-17T19:05:09.365+01:00A long break...As I come back from another long blogging break, a lot of great things have happened in my life...<br />
<br />
The greatest experience I've had so far in my life was on September 15, 2011 I became a father to this wonderfully charming little guy you see below: <br />
<br />
<img alt="" aria-busy="false" aria-describedby="fbPhotosSnowboxCaption" class="spotlight" height="424" src="https://dl.dropbox.com/u/18352048/Photos/331429_10150560003022904_1823838078_o.jpg" width="640" /><br />
<br />
I took a full month off work to play daddy and to assist my wife with everything I possibly can. It was a great time and I'll never regret or forget that.<br />
<br />
My hands were completely tied from work the day I got back from my leave. Luckily the projects were all very exciting and challenging, but did require me to spend a ton of hours on work. I had the chance to work on an online music service called TDC Play for a rather large danish based telecom company called TDC. I unfortunately only took part in the design and development of the Windows Phone 7 version, but the app is also available on the iOS and Android.<br />
<br />
You can check out the app here:<br />
<a href="http://www.windowsphone.com/da-DK/apps/01f8e8d3-d7aa-4bf6-9dcd-38e556c81ee3">http://www.windowsphone.com/da-DK/apps/01f8e8d3-d7aa-4bf6-9dcd-38e556c81ee3</a><br />
...unfortunately, due to infrastructure and licensing issues it's only available to Danish customers<br />
<br />
The app was extremely fun to make and I got the to work with my old colleages from the Microsoft Development Center in Copenhagen. I expect to post some articles on performance, background agents, Implementing a MediaStreamSource for streaming or progressive downloads, and loads of other fun stuff.<br />
<br />
I also got started again in doing some speaking events. In February 29 in Horsons, Denmark I'll be doing a talk on <a href="http://www.danishdevconf.com/speakers/christian-helle/">Windows Phone 7 and HTML5</a> for the <a href="http://danishdevconf.com/">Danish Developer Conference</a> and on February 13 I'll be doing an online talk on <a href="http://www.eventbrite.com/event/2786639915">Background Agents on Windows Phone 7</a><br />
<br />
So what's next for me in the blogsphere? Well to begin with I'd like to continue on my series Multi-platform Mobile Development and some articles on Windows Phone 7 development. I'm looking forward to getting back into writing some useful articles.<br />
<br />
I'll probably also be back on the MSDN forums, especially the Smart Device section to help out other developers running into issues with mobile developmentChristian Resma Hellehttp://www.blogger.com/profile/16521776612083091477noreply@blogger.com2tag:blogger.com,1999:blog-4995334164049002857.post-80291800743648017302011-06-07T08:35:00.004+02:002012-02-21T11:20:29.650+01:00SQL Compact Query AnalyzerI’ve been working extensively on enterprise mobility projects lately. These applications integrate into large SAP based systems and when testing the system it can get very tedious to set up some temporary data from the backend. I’m also working with some not-so-technical testers that get intimidated by the Visual Studio or the SQL Server Management Studio. This led me to writing an open source project called <a href="http://sqlcequery.codeplex.com/">SQL Compact Query Analyzer</a><br />
<br />
Here’s some details I pulled directly off the CodePlex site<br />
<br />
<span class="Apple-style-span" style="background-color: white; color: #30332d; font-family: 'Segoe UI', 'Microsoft Sans Serif', Arial, Geneva, sans-serif; font-size: 13px;"><b>Project Description</b><br />SQL Server Compact Edition Database Query Analyzer<br /><br /><b>Features:</b><br /><br />- Create new database<br />- Automatically refresh database upon executing create/alter/drop table queries<br />- Displays database information (database version, filename, size, creation date)<br />- Displays schema summary (number of tables, columns, primary keys, identity fields, nullable fields)<br />- Displays the information schema views<br />- Displays column information (database type, clr type, max length, allows null, etc)<br />- Displays index information (column name, is unique, is clustered)<br />- Execute SQL Queries against a SQL Server Compact Edition database<br />- Execute multiple SQL queries (delimited by a semi colon ;)<br />- Easily edit the contents of the database<br />- Display query result as XML<br />- Shrink and Compact Databases<br />- SDF file association with SQL Compact Query Analyzer for launching directly by opening the SDF in Windows Explorer<br />- Displays thumbnails for IMAGE fields<br />- Generates Schema and Data Scripts<br />- Supports password protected databases<br />- Supports SQLCE 3.0, 3.1, 3.5 and 4.0<br /><br /><b>Coming Soon:</b><br />- Purge database content<br />- Create, edit, and drop tables UI<br />- Create, edit, and delete table references and indexes UI<br />- Support for SQL Server Compact Edition 2.0<br /><br /><br /><b>Screenshots</b><br /><br /><img src="http://download.codeplex.com/Download?ProjectName=sqlcequery&DownloadId=335445" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; max-width: 100%;" /><br />- Displays database and schema information and executes multiple SQL queries directly<br /><br /><img src="http://download.codeplex.com/Download?ProjectName=sqlcequery&DownloadId=335447" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; max-width: 100%;" /><br />- Edit the table data directly<br /><br /><img src="http://download.codeplex.com/Download?ProjectName=sqlcequery&DownloadId=335444" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; max-width: 100%;" /><br />- Display the contents of IMAGE fields<br /><br /><img src="http://download.codeplex.com/Download?ProjectName=sqlcequery&DownloadId=335456" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; max-width: 100%;" /><br />- Performance numbers for queries<br /><br /><img src="http://download.codeplex.com/Download?ProjectName=sqlcequery&DownloadId=335461" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; max-width: 100%;" /><br />- Query errors<br /><br /><img src="http://download.codeplex.com/Download?ProjectName=sqlcequery&DownloadId=335464" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; max-width: 100%;" /><br />- Output result set as XML<br /><br /><img src="http://download.codeplex.com/Download?ProjectName=sqlcequery&DownloadId=335465" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; max-width: 100%;" /><br />- Create new database<br /><br /><img src="http://download.codeplex.com/Download?ProjectName=sqlcequery&DownloadId=335466" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; max-width: 100%;" /><br />- Shrink, compact, script database<br /><br /><b>Prerequisites:</b><br />- .NET Framework 4.0<br /></span><br />
<br />
Check it out! You might find it useful!Christian Resma Hellehttp://www.blogger.com/profile/16521776612083091477noreply@blogger.com6tag:blogger.com,1999:blog-4995334164049002857.post-39411311213339019452011-03-10T23:17:00.004+01:002012-01-19T14:45:35.026+01:00SQL Compact Code GeneratorMore than a year ago, I published a project on CodePlex called <a href="http://sqlcecodegen.codeplex.com/">SQL Compact Code Generator</a>. Unfortunately, I never managed to find the time to do some work on it and the project was set on a very long hold. A year after I suddenly really needed such a tool and decided that I should put in some hours on the project.<br />
<br />
I'm currently working on a large enterprise project where changes to the database schema is done rather frequently, to avoid the pain of updating my data layer after every change I decided to use my code generator.<br />
<br />
Here's some details I pulled directly off the CodePlex site.<br />
<br />
<span class="Apple-style-span" style="background-color: white; color: #30332d; font-family: 'Segoe UI', 'Microsoft Sans Serif', Arial, Geneva, sans-serif; font-size: 13px;"></span><br />
<div style="margin-bottom: 1em; margin-top: 1em;">
<strong>Project Description</strong><br />Contains a stand alone GUI application and a Visual Studio Custom Tool for automatically generating a .NET data access layer code for objects in a SQL Server Compact Edition database.<br /><br /><strong>Features:</strong></div>
<ul style="list-style-image: url(http://i2.codeplex.com/Images/v18365/doublearrow.gif); list-style-type: none; margin-left: 0em; padding-left: 2em;">
<li style="margin-bottom: 0.3em; margin-left: 0px; margin-top: 0.3em; vertical-align: middle;">Visual Studio 2008 and 2010 Custom Tool Support</li>
<li style="margin-bottom: 0.3em; margin-left: 0px; margin-top: 0.3em; vertical-align: middle;">Creates entity classes for each table in the database</li>
<li style="margin-bottom: 0.3em; margin-left: 0px; margin-top: 0.3em; vertical-align: middle;">Generates data access code that implements the Repository Pattern</li>
<li style="margin-bottom: 0.3em; margin-left: 0px; margin-top: 0.3em; vertical-align: middle;">Generates methods for Create, Read, Update and Delete operations</li>
<li style="margin-bottom: 0.3em; margin-left: 0px; margin-top: 0.3em; vertical-align: middle;">Generates SelectBy and DeleteBy methods for every column in every table</li>
<li style="margin-bottom: 0.3em; margin-left: 0px; margin-top: 0.3em; vertical-align: middle;">Generates a Purge method for every table to delete all records</li>
<li style="margin-bottom: 0.3em; margin-left: 0px; margin-top: 0.3em; vertical-align: middle;">Generates Count() method for retrieving the number of records in each table</li>
<li style="margin-bottom: 0.3em; margin-left: 0px; margin-top: 0.3em; vertical-align: middle;">Generates CreateDatabase() method for re-creating the database</li>
<li style="margin-bottom: 0.3em; margin-left: 0px; margin-top: 0.3em; vertical-align: middle;">Generates xml-doc code comments for entities and data access methods</li>
<li style="margin-bottom: 0.3em; margin-left: 0px; margin-top: 0.3em; vertical-align: middle;">Generates Entity Unit Tests</li>
<li style="margin-bottom: 0.3em; margin-left: 0px; margin-top: 0.3em; vertical-align: middle;">Generates Data Access Unit Tests</li>
<li style="margin-bottom: 0.3em; margin-left: 0px; margin-top: 0.3em; vertical-align: middle;">Generates .NET Compact and Full Framework compatible code</li>
<li style="margin-bottom: 0.3em; margin-left: 0px; margin-top: 0.3em; vertical-align: middle;">Support for SQL Compact Edition version 4.0</li>
<li style="margin-bottom: 0.3em; margin-left: 0px; margin-top: 0.3em; vertical-align: middle;">Multiple test framework code generation (MSTest, NUnit, xUnit)</li>
<li style="margin-bottom: 0.3em; margin-left: 0px; margin-top: 0.3em; vertical-align: middle;">Transaction support per DataRepository instance (Begin, Commit, Rollback)</li>
<li style="margin-bottom: 0.3em; margin-left: 0px; margin-top: 0.3em; vertical-align: middle;">Code generation options to enable/disable unit test code generation</li>
<li style="margin-bottom: 0.3em; margin-left: 0px; margin-top: 0.3em; vertical-align: middle;">Windows Phone 7 "Mango" support for generating a LINQ to SQL DataContext</li>
</ul>
<div style="margin-bottom: 1em; margin-top: 1em;">
<br /><strong>Coming Soon:</strong></div>
<ul style="list-style-image: url(http://i2.codeplex.com/Images/v18365/doublearrow.gif); list-style-type: none; margin-left: 0em; padding-left: 2em;">
<li style="margin-bottom: 0.3em; margin-left: 0px; margin-top: 0.3em; vertical-align: middle;">Generate database maintenance code (clear database, shrink/compress database)</li>
<li style="margin-bottom: 0.3em; margin-left: 0px; margin-top: 0.3em; vertical-align: middle;">Support for multiple versions of SQL Server Compact Edition</li>
<li style="margin-bottom: 0.3em; margin-left: 0px; margin-top: 0.3em; vertical-align: middle;">VB.NET Code Support</li>
<li style="margin-bottom: 0.3em; margin-left: 0px; margin-top: 0.3em; vertical-align: middle;">Visual Studio Add-in</li>
</ul>
<div style="margin-bottom: 1em; margin-top: 1em;">
<br /><br /><strong>Screenshots:</strong></div>
<div style="margin-bottom: 1em; margin-top: 1em;">
<strong></strong><img alt="" src="http://download.codeplex.com/download?ProjectName=sqlcecodegen&DownloadId=256691" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; max-width: 100%;" /></div>
<div style="margin-bottom: 1em; margin-top: 1em;">
<strong>NEW: </strong>Custom Tool for Windows Phone 7 "Mango"</div>
<div style="margin-bottom: 1em; margin-top: 1em;">
<br /><img alt="" src="http://download.codeplex.com/download?ProjectName=sqlcecodegen&DownloadId=256711" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; max-width: 100%;" /><br />Custom Tool<br /><br /><img alt="" src="http://download.codeplex.com/download?ProjectName=sqlcecodegen&DownloadId=219216" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; max-width: 100%;" width="800" /><br />Generating Entity Classes<br /><br /><img alt="" src="http://download.codeplex.com/download?ProjectName=sqlcecodegen&DownloadId=219219" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; max-width: 100%;" width="800" /><br />Generating Data Access methods that implement the Repository Pattern<br /><br /><img alt="" src="http://download.codeplex.com/download?ProjectName=sqlcecodegen&DownloadId=217329" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; max-width: 100%;" width="800" /><br />Generating Entity Unit Tests<br /><br /><img alt="" src="http://download.codeplex.com/download?ProjectName=sqlcecodegen&DownloadId=217330" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; max-width: 100%;" width="800" /><br />Generating Data Access Unit Tests to validate the integrity between the data layer and the actual database</div>
<br />
<br />
<br />
<span class="Apple-style-span" style="color: #30332d; font-family: 'Segoe UI', 'Microsoft Sans Serif', Arial, Geneva, sans-serif; font-size: x-small;"><b><span class="Apple-style-span" style="font-size: 13px; font-weight: normal;"></span></b></span>Check it out! You might find it useful too...Christian Resma Hellehttp://www.blogger.com/profile/16521776612083091477noreply@blogger.com6tag:blogger.com,1999:blog-4995334164049002857.post-88671653191079679452011-02-10T15:15:00.001+01:002011-02-10T15:18:39.363+01:00How to display a Notification Bubble in Windows Mobile using .NETCFYesterday, I found myself using an old piece of code that I wrote ages ago. It's something I've used every now and then for past few years. Since I myself find it useful, I might as well share it. All the code does is display a Notification Bubble in Windows Mobile. To do this you use the <a href="http://msdn.microsoft.com/en-us/library/microsoft.windowsce.forms.notification.aspx">Notification</a> class in the Microsoft.WindowsCE.Forms namespace. Even though the Notification class is very straight forward and easy to use, I created a helper class so that I only need to write one line of code for displaying a notification bubble: NotificationBubble.Show(2, "Caption", "Text");
<br/><br/>
<div style="font-family: Fixedsys; font-size: 10pt; color: black; background: white;"><pre style="margin: 0px;"><span style="color: gray;">///</span><span style="color: green;"> </span><span style="color: gray;"><summary></span></pre><pre style="margin: 0px;"><span style="color: gray;">///</span><span style="color: green;"> Used for displaying a notification bubble</span></pre><pre style="margin: 0px;"><span style="color: gray;">///</span><span style="color: green;"> </span><span style="color: gray;"></summary></span></pre><pre style="margin: 0px;"><span style="color: blue;">public</span> <span style="color: blue;">static</span> <span style="color: blue;">class</span> <span style="color: #2b91af;">NotificationBubble</span></pre><pre style="margin: 0px;">{</pre><pre style="margin: 0px;"> <span style="color: gray;">///</span><span style="color: green;"> </span><span style="color: gray;"><summary></span></pre><pre style="margin: 0px;"> <span style="color: gray;">///</span><span style="color: green;"> Displays a notification bubble</span></pre><pre style="margin: 0px;"> <span style="color: gray;">///</span><span style="color: green;"> </span><span style="color: gray;"></summary></span></pre><pre style="margin: 0px;"> <span style="color: gray;">///</span><span style="color: green;"> </span><span style="color: gray;"><param name="duration"></span><span style="color: green;">Duration in which the notification bubble is shown (in seconds)</span><span style="color: gray;"></param></span></pre><pre style="margin: 0px;"> <span style="color: gray;">///</span><span style="color: green;"> </span><span style="color: gray;"><param name="caption"></span><span style="color: green;">Caption</span><span style="color: gray;"></param></span></pre><pre style="margin: 0px;"> <span style="color: gray;">///</span><span style="color: green;"> </span><span style="color: gray;"><param name="text"></span><span style="color: green;">Body</span><span style="color: gray;"></param></span></pre><pre style="margin: 0px;"> <span style="color: blue;">public</span> <span style="color: blue;">static</span> <span style="color: blue;">void</span> Show(<span style="color: blue;">int</span> duration, <span style="color: blue;">string</span> caption, <span style="color: blue;">string</span> text)</pre><pre style="margin: 0px;"> {</pre><pre style="margin: 0px;"> <span style="color: blue;">var</span> bubble = <span style="color: blue;">new</span> <span style="color: #2b91af;">Notification</span></pre><pre style="margin: 0px;"> {</pre><pre style="margin: 0px;"> InitialDuration = duration,</pre><pre style="margin: 0px;"> Caption = caption,</pre><pre style="margin: 0px;"> Text = text</pre><pre style="margin: 0px;"> };</pre><pre style="margin: 0px;"> </pre><pre style="margin: 0px;"> bubble.BalloonChanged += OnBalloonChanged;</pre><pre style="margin: 0px;"> bubble.Visible = <span style="color: blue;">true</span>;</pre><pre style="margin: 0px;"> }</pre><pre style="margin: 0px;"> </pre><pre style="margin: 0px;"> <span style="color: blue;">private</span> <span style="color: blue;">static</span> <span style="color: blue;">void</span> OnBalloonChanged(<span style="color: blue;">object</span> sender, <span style="color: #2b91af;">BalloonChangedEventArgs</span> e)</pre><pre style="margin: 0px;"> {</pre><pre style="margin: 0px;"> <span style="color: blue;">if</span> (!e.Visible)</pre><pre style="margin: 0px;"> ((<span style="color: #2b91af;">Notification</span>)sender).Dispose();</pre><pre style="margin: 0px;"> }</pre><pre style="margin: 0px;">}</pre></div>
<br/><br/>
Hope you found this helpful.Christian Resma Hellehttp://www.blogger.com/profile/16521776612083091477noreply@blogger.com0