-
Notifications
You must be signed in to change notification settings - Fork 0
/
feed.xml
507 lines (318 loc) · 38.4 KB
/
feed.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
<feed xmlns="http://www.w3.org/2005/Atom"><title type="text">Shannon's Blog</title><subtitle type="text">Shannon's Blog</subtitle><id>http://blog.shannonlewis.me/</id><updated>2016-09-03T10:59:23+10:00</updated><author><name>Shannon Lewis</name><uri>http://blog.shannonlewis.me</uri><email>[email protected]</email></author><generator>Sandra.Snow Atom Generator</generator><link rel="alternate" href="http://blog.shannonlewis.me/feed.xml" /><link rel="self" type="text/html" title="Shannon's Blog" href="http://blog.shannonlewis.me/feed.xml" /><entry><id>http://blog.shannonlewis.me/2015/07/orienteer-origins/</id><title type="text">Orienteer's Origins</title><summary type="html"><p>I quick look back at my Orienteer journey.</p>
</summary><published>2015-07-20T14:00:00Z</published><updated>2015-07-20T14:00:00Z</updated><link rel="alternate" href="http://blog.shannonlewis.me/2015/07/orienteer-origins/" /><content type="html"><p>In working through finally publishing Orienteer recently I spent some time looking back over the code, how it came to be and how it had evolved over the last few years. It was an interesting journey, one I've really enjoyed and one I've learned a lot from. Here are some of the highlights.</p>
<h2>Phase 1 - Windows 8 and getting mobile</h2>
<p>When Windows 8 beta arrived I picked up the SDKs and samples and started learning. Having a WPF and C# background I went down the C#/XAML path, rather than WinJS.</p>
<p>I dug around in a number of the samples and went looking for something I could build. Not because I really wanted to publish an app, what I was looking for was something I could use as a learning tool. A learning tool not just for me, but something I could use to illustrate concepts and features to others.</p>
<p>What I wanted was something (a domain) people could understand quickly and easily but still allow me to incorporate as many of the features Windows 8 had to offer.</p>
<p>Like many others I know, I like to listen to music while I'm working. So one day I started up the Music app that came with Windows 8 and found it a bit frustrating to use. If there was a way to do a playlist, I couldn't find it (remember this was in the days of the Beta, the app is a bit different now).</p>
<p>After a short time messing around with it I decided this was the type of app I'd been looking for. It ticked all of the following boxes for things I wanted to learn more about:</p>
<ul>
<li>Reading/writing files</li>
<li>Rendering grouped lists, with semantic zoom</li>
<li>Touch interactions/manipulations</li>
<li>Tiles and pinning</li>
<li>Settings</li>
<li>Background execution</li>
<li>Search </li>
</ul>
<h2>Phase 2 - Grooving along</h2>
<p>So with great enthusiasm I set off building my imaginatively named Jukebox application, and in not too long had the core features roughly working and I could list and play the music in my music library. After a few months of tinkering in my spare time I had working examples of all of the things on my list.</p>
<h2>Phase 3 - First an app, then a framework</h2>
<p>This was the point at which Orienteer was born. Throughout the development of the app I had built and used controller based navigation, because that's what I liked from my WPF days and time spent with the Magellan Navigation Framework. In order to be able to reuse this code I started refactoring it out, dare I say "into a framework".</p>
<p>As a quick aside, Orienteer had a different name at that stage. I originally called it Slab, and it was originally going to contain far more than it does today. For example, it originally contained the PresentationBus, before I pulled that out and made it into its own library.</p>
<h2>Phase 4 - "Why not have both?"</h2>
<p>During the evolution of Orienteer I also started doing mobile development for Windows Phone 8, and iOS and Android, using Xamarin and Xamarin Forms. So the question I then had was "Do I stick with Windows 8 (tablet) or do I go mobile?". Given that Windows 8, Windows Phone 8 and Xamarin Forms are all XAML based, it turned out to be a case of "Why not have both?".</p>
<h2>Windows 8 Jukebox</h2>
<p>I've recently opened up the source code for the Jukebox app, you can find it <a href="https://github.com/slewis74/Jukebox">on GitHub</a>. In a future post I'll go through each of the feature bullets points from above and talk about implementation specifics.</p>
<h2>Reflections</h2>
<p>So did I get what I wanted out of my journey with Orienteer? Yes, absolutely.</p>
<p>I learned a lot about Windows 8, mobile development in general and the satisfaction of publishing something of your own.</p>
<p>A couple of things that stand out.</p>
<p><strong>Publish early!</strong></p>
<p>The core code for Orienteer was "almost ready" for a long time, but I was hesitant about releasing it. I think this was partly due to the origins in Windows 8. With the lacklustre uptake of Windows 8 I started questioning whether Orienteer would be viable. The inclusion of the other mobile platforms put those doubts to rest, but the delay cost me time in getting feedback and input from others.</p>
<p><strong>Do what you enjoy</strong></p>
<p>Yes, it sounds very cliche, but building Orienteer (and even the sample apps for that matter) has been something I've really enjoyed. Being the Product Owner is also a great learning experience.</p>
<h2>Looking forward...</h2>
<p>To Windows 10!</p>
</content></entry><entry><id>http://blog.shannonlewis.me/2015/07/orienteer-winphone/</id><title type="text">Orienteer and Windows Phone</title><summary type="html"><p>Orienteer now has support for Windows Phone 8 Silverlight apps!</p>
</summary><published>2015-06-30T14:00:00Z</published><updated>2015-06-30T14:00:00Z</updated><link rel="alternate" href="http://blog.shannonlewis.me/2015/07/orienteer-winphone/" /><content type="html"><p>Orienteer now has support for Windows Phone 8 Silverlight apps, and there's a <a href="https://github.com/slewis74/Orienteer/tree/master/Samples/WinPhoneSample">sample app</a>.</p>
<p>The bulk of the setup code is very similar to that of the Xamarin Forms applications, with the exception of the PhoneApplicationFrameAdapter.</p>
<h2>PhoneApplicationFrameAdapter</h2>
<p>To hook Orienteer into Xamarin Forms we use a custom NavigationPage, to hook in to Windows Phone we use an adapter that attaches to the PhoneApplicationFrame. The code below shows how to initialize the adapter during the application initialization.</p>
<pre><code>private IContainer _container;
private void InitializePhoneApplication()
{
if (phoneApplicationInitialized)
return;
LetThereBeIoC();
RootFrame = new PhoneApplicationFrame();
RootFrame.Navigated += CompleteInitializePhoneApplication;
RootFrame.NavigationFailed += RootFrame_NavigationFailed;
RootFrame.Navigated += CheckForResetNavigation;
InitFrameAdapter();
phoneApplicationInitialized = true;
}
private async Task InitFrameAdapter()
{
var adapter = _container.Resolve&lt;IPhoneApplicationFrameAdapter&gt;();
adapter.PhoneApplicationFrame = RootFrame;
await adapter.DoStartup();
}
private void LetThereBeIoC()
{
var builder = new ContainerBuilder();
builder.RegisterAssemblyModules(new[]
{
typeof(App).Assembly
});
_container = builder.Build();
}
</code></pre>
<h3>Autofac registration</h3>
<p>To register the adapter in Autofac you will need a registration similar to the following</p>
<pre><code>builder
.RegisterType&lt;PhoneApplicationFrameAdapter&gt;()
.As&lt;IPhoneApplicationFrameAdapter&gt;()
.WithParameter("viewRootNamespace", ViewRootNamespace)
.WithParameter("baseFeatureFolder", "Features")
.SingleInstance();
</code></pre>
<p>Where:</p>
<ul>
<li>ViewRootNamespace is the same namespace used by the ViewLocator</li>
<li>"Features" is the ViewRootNamespace's folder, relative to the root level of the application.</li>
</ul>
<p>These values are used by the adapter to determine the correct XAML file to navigate to, when a ViewModelNavigationRequest is published.</p>
<h3>Manifest Navigation Page</h3>
<p>In the Windows Phone manifest there is a value for the default page to navigate to. Orienteer doesn't use this value, it uses the NavigationStack's defaultRoute to determine the default route, and therefore page, to display. It does however have to understand what the value is.</p>
<p>The reason behind this is that the PhoneApplicationFrame itself will navigate to the specified page upon startup and cause issues with Orienteer's stack monitoring.</p>
<p>You have a couple of options around this value:</p>
<ol>
<li><p>Set the value to Orienteer, per the WinPhoneSample
<img src="http://blog.shannonlewis.me/images/wp8-manifest-navpage.png" width="360px" height="262px"/></p></li>
<li><p>Set the value to be blank, and ignore the red text that appears in Visual Studio's manifest editor.</p></li>
<li><p>Choose your own custom value. In this scenario you will also need to set assign the custom value to the ManifestNavigationPage property of the adapter, for example in the Autofac registration you'd include something like </p>
<pre><code>.WithProperty("ManifestNavigationPage", "MyCustomValue")
</code></pre></li>
</ol>
</content></entry><entry><id>http://blog.shannonlewis.me/2015/06/orienteer/</id><title type="text">Orienteer</title><summary type="html"><p>Navigating in MVVM, which way do you go?</p>
</summary><published>2015-06-14T14:00:00Z</published><updated>2015-06-14T14:00:00Z</updated><link rel="alternate" href="http://blog.shannonlewis.me/2015/06/orienteer/" /><content type="html"><p>Several years ago I set out into the world of mobile app development. As a developer focused primarily in the Microsoft space, and having spent a good part of the last 8 years doing WPF development, Windows 8 and Windows Phone 8 apps seemed like a logical place to start.</p>
<p>Over the years I've used numerous frameworks and tools, some of which I've grown to love, and others not so much. One that I am particularly fond of, which was written by a friend and ex-colleague, is the <a href="https://code.google.com/p/magellan-framework/">Magellan navigation framework for WPF</a>.</p>
<p>The MVC style navigation and the removal of the navigation logic and data retrieval from the ViewModels makes so much sense to me, and when I started off into the mobile XAML world I found I was missing my controllers. So over the course of the last 2-3years, and several projects, I've been slowly putting together something very similar, but a bit smaller and more mobile focused. Introducing the result...</p>
<h2>Orienteer</h2>
<p>Orienteer is available as a <a href="https://www.nuget.org/packages/Orienteer/">nuget package</a>, and the <a href="https://github.com/slewis74/Orienteer">project page</a> can be found over on GitHub.</p>
<h3>What's in the box?</h3>
<p>Let's have a look at some of the core components and features.</p>
<h4>Controllers and the Navigator</h4>
<p>The core to navigating is a Navigator. Any of the commands that need to trigger a navigation simply need to take a dependency on a Navigator, it provides the gateway to the controller actions.</p>
<p>Controllers are controllers in the MVC, not the iOS sense, for those who've done iOS development. An action can return a ViewModelResult, in order to navigate to the View (page) associated with that ViewModel. An action can also return a DataActionResult, which only contains data (ViewModels can access these actions via the GetData methods on the Navigator).</p>
<p>As a note, I haven't needed modals in the apps I've looked at so far, so no support for that yet but it's on the backlog.</p>
<h4>ViewModel first navigation</h4>
<p>As mentioned above, the controller actions can return a result identifying the ViewModel to navigate to, i.e. it uses ViewModel first navigation. The View is located by naming convention, using a parallel hierarchy search from configured root namespaces for the Views and ViewModels.</p>
<p>So the Views and ViewModels may reside in the same folder, in which case the root namespaces match, or they may reside below separate root level folders. As an example of the latter, you might have ViewModels/Feature1/SomeViewModel.cs and it corresponding view might be Views/Feature1/SomeView.xaml </p>
<h4>Routing</h4>
<p>Orienteer also supports routing similar to MVC. For example, we could have a route that looks like the following</p>
<pre><code>/contacts/search?name=smith
</code></pre>
<p>This would call the Search action on the ContactsController, passing a value of 'smith' to the name parameter.</p>
<p>There were 2 reasons for needing this, first is the routes for the current pages in the navigation stack are persisted, if required, so the stack can be restored on a restart of the app.</p>
<p>Second, on Windows Phone and Windows 8 it's used for deep linking from pinned tiles.</p>
<h4>Async support</h4>
<p>The Navigator and Controller actions have full support for async/await. So you can NavigateAsync to a Controller action that is awaiting data retrieval.</p>
<h4>Automatic Dispatching</h4>
<p>The BindableBase and DispatchingObservableCollection both automatically dispatch all Changed events back onto the UI thread. So if you have background data loads happening you never have to worry about dispatching.</p>
<p>While we're on DispatchingObservableCollection, it also has support for LargeUpdates. Once you start a Large update the CollectionChanged events are suppressed until you call complete, at which point a Reset is raised. This is useful in scenarios where you know there'll be a large amount of items being added and you don't want the performance hit of a re-paint per Add.</p>
<h4>NavigationFrame</h4>
<p>In Windows 8 the inbuilt navigation Frame has some interesting behaviour regarding the way it caches or recreates Views when you navigate Back. To work around this Orienteer has it's own NavigationFrame for Windows 8.</p>
<h4>Xamarin Forms Support</h4>
<p>Being XAML based, the navigation concepts that Orienteer uses fit in quite well with Xamarin Forms, so it's supported out of the box.</p>
<h3>Sample Code</h3>
<p>To help get going with Orienteer there is are samples included with the source. At the time of writing this post the Xamarin Forms sample is complete. Windows Phone and Windows 8 will be coming shortly.</p>
<p>The samples currently all revolve around a simple app to display the music content on your device. The Windows 8 sample that's coming will also include playing functionality, to help illustrate some more decoupling concepts and some more advanced uses of the <strong><a href="http://www.nuget.org/packages/Slew.PresentationBus/">PresentationBus</a></strong>.</p>
<p>The samples also use Autofac, being my container of choice, with illustration of how to configure it for use with Orienteer. Orienteer itself has no direct dependency to Autofac though, so feel free to use your container of choice.</p>
<h4>Windows Phone</h4>
<p>If you run the Windows Phone app on the emulator you'll want to connect some music files to the emulator. I'd recommend using the Windows Phone 8.1 Emulator. In the SD Card configuration select a folder that contains some Music files and select Insert Card. You'll get a prompt in the emulator at that point, select Yes and you're away.</p>
<p>Note that the Windows Phone emulator resets its state on each restart, you have to select to Insert Card each time you restart it.</p>
<h4>Android</h4>
<p>Again, on the emulator you'll want some music files. If you open an Android console you can use </p>
<pre><code>adb push someMusicFolder /sdcard/
</code></pre>
<p>This will copy the files onto the emulator.</p>
<h4>iOS</h4>
<p>On iOS, I haven't found a way to get music onto the emulator as yet. The MusicProvider class for iOS currently returns some static data by default. If you're running on a device then commenting out the static data code at the top of the ScanMusicLibraryFolder method.</p>
<h2>Stay Tuned</h2>
<p>While the samples should hopefully help those who are eager to give Orienteer a go, I'm also aiming to do some more detailed posts on setup and usage soon. </p>
</content></entry><entry><id>http://blog.shannonlewis.me/2015/05/viewcomposition/</id><title type="text">Composing views</title><summary type="html"><p>In case of massive XAML files, break here...</p>
</summary><published>2015-05-24T14:00:00Z</published><updated>2015-05-24T14:00:00Z</updated><link rel="alternate" href="http://blog.shannonlewis.me/2015/05/viewcomposition/" /><content type="html"><p>A while back I talked about <a href="http://blog.shannonlewis.me/2014/06/xaml-commands/">XAML and Commands</a>, and I mentioned UI decoupling using something like an EventAggregator. In that post I was focusing on the separation of the command logic into Command objects and how that decouples the UI implementation. In this post we'll expore some more decoupling ideas.</p>
<h2>View Composition</h2>
<p>Something I commonly see in WPF and Xaml, where MVVM has been used, are massive ViewModels. When you dig into these you'll usually find that there are in fact multiple view models that have all been jammed into the one class. The tendency seems to come down to </p>
<pre><code>1 Page = 1 View = 1 ViewModel.
</code></pre>
<p>One of the things that initially seems nice about this arrangement is that we have easy access to everything we need. There's lots of properties and command objects and all sorts of goodies within easy reach, just begging to be coupled together. Where it leads though is an unhappy place.</p>
<p>Ok, so we're in an unhappy place, where do we go? We start to decouple the code and separate out the pieces. Let's say we've got a view that has a search panel, a panel with a list of results and a panel to display the details of whichever item in the list is selected. Each of these 3 concerns should have it's own View (user control) and ViewModel, the page's View and ViewModel are then host to the other 3. </p>
<p>So this sounds good and we start pulling the code apart, let's start with the search panel. And with that we come to a screeching halt. If the search code is in a separate ViewModel, how is it going to update the results list that is now in a different class? We'll hit a similar thing when we split the list and the details for the selected item, how does the details panel know which item is selected? </p>
<p>What we're seeing here is the difference between a coupled UI and a composed UI. A composed UI, as the name should suggest, is built up of components that are independent. They do not have direct knowledge of what other components are in use around them, but we need a way for them to interact with the other components.</p>
<p>I liken this to micro-service architecture, where you also have a number of services indirectly interacting with one another. How do they achieve that interaction? Commonly through a Service Bus of some kind, i.e. through messaging. So maybe our ViewModels could interact through message to achieve a similar result?</p>
<h2>Messaging and the PresentationBus</h2>
<p>This is the scenario where the EventAggregator comes into play. Now at this point let's clarify that despite the name, it doesn't actually Aggregate Events. What it does is broker Events between a Publisher and a number of Subscribers. I'm not sure on the exact origins of the name, but it's been commonly used for the message brokers in a number of frameworks (e.g. Unity, Caliburn Micro) for a very long time.</p>
<p>As part of several side projects I've been working on, I've also built an implementation of an event broker that I called <strong><a href="http://www.nuget.org/packages/Slew.PresentationBus/">PresentationBus</a></strong> (i.e. a Service Bus for the "Presentation Layer").</p>
<p>In a future post I'll go through some more about PresentationBus and illustrate some more examples of its use.</p>
</content></entry><entry><id>http://blog.shannonlewis.me/2015/03/mvvm/</id><title type="text">Model-View-ViewModel</title><summary type="html"><p>Don't forget the first M!</p>
</summary><published>2015-03-26T14:00:00Z</published><updated>2015-03-26T14:00:00Z</updated><link rel="alternate" href="http://blog.shannonlewis.me/2015/03/mvvm/" /><content type="html"><p>As a consultant focused in the WPF and Mobile development spaces I've spent a lot of time in the world of MVVM. I've seen lots of different frameworks and lots of different ideas around implementing MVVM.</p>
<p>One thing that I've seen frequently cause confusion is the first M. To help explain that statement, here are the typical ways I try to describe MVVM to people.</p>
<h2>What is MVVM?</h2>
<p>Model-View-ViewModel. That's what it's short for.</p>
<p>MVVM is an adaptation of MVP and MVC, adjusted to play to the strengths of XAML's binding abilities. </p>
<p>It also abstracts the visual behaviour away from the View and into a ViewModel, which is just a class at the end of the day, and in doing so it becomes possible to unit test the visual behaviour without an actual UI.</p>
<h2>What is a Model?</h2>
<p>A Model represents data. The data may be a single entity, it might be an aggregate of multiple model entities.
Its responsibility is to hold the data and notify others when changes occur. It is the Domain Model of your client app.</p>
<p>A model object <strong>instance</strong> may be shared between ViewModel instances.</p>
<h2>What is a View Model?</h2>
<p>A View Model represents the visual state of the data, and encapsulates the visual behaviour around that data. It may project the data stored in a model (e.g. FullName may project "Surname, FirstName"), but it's responsibility is to hold the transient, visual state of the data. IsSelected, IsChecked, IsEnabled, SelectedItem are examples of the types of properties on a ViewModel, they are not persisted but are important to the visualisation of the data.</p>
<p>A ViewModel <strong>type</strong> may be shared between Views, but <a href="http://en.wikipedia.org/wiki/Here_be_dragons">here be dragons</a>. Only do this if the visual behaviour required <strong>is identical</strong>. If it isn't identical then you will be tempted into adding multiple personalities to the ViewModel, and violating the "Single Responsibility" principle. </p>
<h2>What is a View?</h2>
<p>A View presents the data to a user, through the use of ViewModels and Models. A View can use a Model directly, if there is no requirement for visual state.</p>
<p>A View may also consist of sub-Views.</p>
<h2>Don't forget the first M!</h2>
<p>So back to my earlier statement, many implementations I've seen have lots of Views and ViewModels, but not a Model in sight. The first M (Model) gets neglected.</p>
<p>When you dig deeper there usually are Models, but they've been called ViewModels. How does the code get to this point? I think it's often that the pattern is not well understood and the team get into the habit of just calling everything a ViewModel, then they start sharing something called a ViewModel (but is actually a Model) between Views, then they get into the habit of doing that, then they start sharing ViewModels that really are ViewModels between Views, then the dragons...</p>
<p>So please, take the time to think about the first M, and avoid confusion by calling things what they actually are.</p>
</content></entry><entry><id>http://blog.shannonlewis.me/2014/06/xaml-commands-and-user-feedback/</id><title type="text">Commands not executing, but why?</title><summary type="html"><p>So now that you've <a href="http://blog.shannonlewis.me/2014/06/xaml-commands/">embraced commands</a>, let's look at how we might provide a slightly better experience for users.</p>
</summary><published>2014-06-11T14:00:00Z</published><updated>2014-06-11T14:00:00Z</updated><link rel="alternate" href="http://blog.shannonlewis.me/2014/06/xaml-commands-and-user-feedback/" /><content type="html"><p>So now that you've <a href="http://blog.shannonlewis.me/2014/06/xaml-commands/">embraced commands</a>, let's look at how we might provide a slightly better experience for users.</p>
<h2>But why can't I execute?</h2>
<p>In several WPF projects I've worked on we've had the requirement to feedback information to the user about why a button cannot currently execute. Usually this will be due to some sort of validation condition failing.</p>
<p>Enter a weakness in ICommand. It provides</p>
<pre><code>bool CanExecute(object value);
</code></pre>
<p>for you to implement logic to determine whether the command can execute, given a parameter value. The limitation is that you can't provide explanation as to why the command can't execute.</p>
<p>For these scenarios, a base class along the lines of the following has worked well</p>
<pre><code>public abstract class Command : ICommand, INotifyPropertyChanged
{
public event EventHandler CanExecuteChanged;
public bool CanExecute(object value)
{
return Errors.Any() == false;
}
public bool HasErrors { get { return Errors.Any(); } }
public virtual IEnumerable&lt;string&gt; Errors
{
get
{
return Enumerable.Empty&lt;string&gt;();
}
}
public void Execute(object value)
{
if (!CanExecute(value))
return;
DoExecute(value);
}
protected abstract void DoExecute(object value);
protected void RaiseCanExecuteChanged()
{
var handler = CanExecuteChanged;
if (handler != null)
{
handler(this, EventArgs.Empty);
}
NotifyChanged("HasErrors");
}
private void NotifyChanged(string propertyName)
{
// details intentionally left blank
}
}
</code></pre>
<p>So now with <a href="http://msdn.microsoft.com/en-us/library/system.windows.controls.tooltipservice.showondisabled(v=vs.110).aspx">a little bit of trickery</a>, you can bind up a button along the lines of</p>
<pre><code>&lt;Button
Command="{Binding SomeCommand}"
ToolTipService.ShowOnDisabled="True"
Content="Disabled Button"&gt;
&lt;Button.ToolTip Visibility="{Binding SomeCommand.HasErrors, Converter={StaticResource BooleanToVisibilityConverter}}"&gt;
&lt;ToolTip&gt;
&lt;ItemsControl ItemsSource="{Binding SomeCommand.Errors}"/&gt;
&lt;/ToolTip&gt;
&lt;/Button.ToolTip&gt;
&lt;/Button&gt;
</code></pre>
<p>Depending on the application, and the likelihood of a large list of errors, you may also need to extend this to include some fixed sizing of the Tooltip and a ScrollViewer.</p>
<h2>Mobile XAML</h2>
<p>In mobile apps you don't have the same options for user feedback, Tooltips don't exist in that world, but the errors are likely to still be useful to the user. I'm still looking for a good solution in the mobile space, so stay tuned. </p>
</content></entry><entry><id>http://blog.shannonlewis.me/2014/06/xamarin-android-parallels/</id><title type="text">Xamarin, Android and Parallels</title><summary type="html"><p>In this post I'll go through some options for debugging Android applications using Visual Studio and Xamarin Studio.</p>
</summary><published>2014-06-10T14:00:00Z</published><updated>2014-06-10T14:00:00Z</updated><link rel="alternate" href="http://blog.shannonlewis.me/2014/06/xamarin-android-parallels/" /><content type="html"><p>In working on a recent project I tried a couple of different debugging configurations while developing an Android app.</p>
<p>Following is what I learned along the way...</p>
<h2>My setup</h2>
<p>Before we go too far, I'm running a Mac Book Pro with Mavericks, Parallels 9 and a Windows 8.1 VM. </p>
<h2>Android Emulators</h2>
<p>I'll jump ahead slightly here to talk emulators. There are a couple of options available.</p>
<p>The option most popular with others on the recent project team was the <a href="http://www.genymotion.com/" title="GenyMotion">GenyMotion</a> emulator. It is fast and robust, but it isn't free.</p>
<p>I went with the emulator that comes with the SDK and found it to be quite workable, assuming you have the Intel HAXM working and you don't move it onto your second display (<a href="https://code.google.com/p/android/issues/detail?id=38371">if you do it will crash next time you start it</a>).</p>
<h3>Intel HAXM Hotfix</h3>
<p>There was an issue with earlier versions of Intel HAXM when running in conjunction with Parallels. The <a href="https://software.intel.com/en-us/blogs/2013/11/06/intelr-haxm-hot-ffixes-for-os-x-mavericks-109-and-windows-81-available-for" title="hotfix">hotfix</a> would previously have to be installed manually, but should now be included in the Intel HAXM installer.</p>
<p>You'll know if it's not applied, because when you try to start an x86 based emulator image it'll hang the entire machine.</p>
<h2>Installing the Android SDK(s)</h2>
<p>The Xamarin installer will install the Android SDK with a number of defaults.</p>
<p>A lesson I learned quickly was to be selective when installing support for extra versions. If you simply tick the top level checkbox for a given API level, in the SDK Manager, it will install the SDK plus a number of emulator images, most of which you don't want. I stuck to installing just the SDK and the x86 emulator image, in OS X. In the Windows VM I had no intention of running the emulator so only installed the SDK itself. </p>
<h2>Debugging</h2>
<p>Debugging from Xamarin Studio in OS X was straightforward and worked without any real issue or special configuration.</p>
<h3>Preserving data</h3>
<p>Depending on your app, you may want to find the option to stop the app data from being cleared on each deploy. The default setting, in both Xamarin Studio and Visual Studio, will clear all app data from the emulator/device every time you run the app.</p>
<p>To changing the setting in Xamarin Studio:</p>
<ul>
<li>Open the Preferences window</li>
<li>Locate the Projects/Android settings</li>
<li>Tick the "Preserve data/cache between application deploys"</li>
</ul>
<p>In Visual Studio:</p>
<ul>
<li>Open the Tools/Options window</li>
<li>Locate the Xamarin/Android settings</li>
<li>Tick the "Preserve data/cache between application deploys"</li>
</ul>
<h3>Parallels</h3>
<p>For part of the project I developed using Xamarin Studio in OS X. This worked, to a point, but for a number of reasons that I won't go into here I wanted to get back to Visual Studio.</p>
<p>Being new to OS X, Xamarin and Android I came in with a steep learning curve in front of me. Fortunately <a href="http://chrisriesgo.com/android-emulator-debugging-from-parallels-to-os-x/">others had already blazed a trail</a>, and <a href="http://stackoverflow.com/questions/1754162/remote-debugging-with-android-emulator">with a little extra help</a> I was well on the way. </p>
<p>Some further notes to this:</p>
<ul>
<li>When you need the Android SDK path is shown at the top of the Android SDK Manager window </li>
<li>ADB ends up in your profile folder, in Windows. For me, the following script worked<br/><br/>
<strong>"%USERPROFILE%\AppData\Local\Android\android-sdk\platform-tools\adb" kill-server</strong>
<strong>"%USERPROFILE%\AppData\Local\Android\android-sdk\platform-tools\adb" start-server</strong>
<strong>"%USERPROFILE%\AppData\Local\Android\android-sdk\platform-tools\adb" devices</strong><br/><br/></li>
<li>Xamarin Studio may sometimes require a Refresh to see the emulator correctly in the list of available devices.</li>
<li>Visual Studio must be started after the emulator and all other SSH config. It will only display the emulators it can see when it first starts. <strong>If the list changes, you must restart Visual Studio</strong>.</li>
<li>When configuring the SSH tunnel in PuTTY, the name/IP required can change depending on the network you are connected to. If the Remote Login settings in OS X read like an IP address then use that IP address, if they don't then use the exact value shown.</li>
<li>The Remote Login settings in OS X show <em>username</em>@<em>machinename</em>. The <strong><em>username</em>@</strong> can also be used in front of the IP/machine name in the PuTTY config, so you don't have to type the admin username each time you connect it, you'll just need to type the password. </li>
</ul>
</content></entry><entry><id>http://blog.shannonlewis.me/2014/06/xaml-commands/</id><title type="text">XAML and Commands</title><summary type="html"><p>A look at the pitfalls of DelegateCommands, and the alternatives.</p>
</summary><published>2014-06-08T14:00:00Z</published><updated>2014-06-08T14:00:00Z</updated><link rel="alternate" href="http://blog.shannonlewis.me/2014/06/xaml-commands/" /><content type="html"><p>During a recent discussion with some developers new to XAML we got onto the topic of Commands. During the discussion I went over some experiences from previous projects, with emphasise on one particular pain point. </p>
<h2>Where does it hurt?</h2>
<p>One of the most common pain points I've come across relates to implementations around the command pattern. The particular pain comes down to the <a href="http://en.wikipedia.org/wiki/Command_pattern">receiver</a> being a ViewModel. This works for simple cases, but can quickly lead to bloating and the ViewModel taking on too many responsibilities/personalities.</p>
<p>What does the manifestation look like?</p>
<h3>DelegateCommand/RelayCommand</h3>
<p>Included in many of the XAML/MVVM frameworks is the concept of a delegate command. This is an implementation of ICommand that takes an Action to execute and a Func<bool> to determine CanExecute. In the constructor you'll see something like this</p>
<pre><code>SomeCommand = new DelegateCommand(() =&gt; DoSomething(), () =&gt; someCondition);
</code></pre>
<p>Then throughout your view model you will then find </p>
<pre><code>SomeCommand.RaiseCanExecuteChanged();
</code></pre>
<p>anywhere there's code that could change the result of the CanExecute condition.</p>
<h3>No commands</h3>
<p>A variation on this is used by Caliburn Micro. What it does differently is that the ViewModel code doesn't use an ICommand derived command object. It instead relies on methods and properties on the ViewModel, which it then wires to UI triggers and enabled properties. There's no object to create, so no code in the constructor, but you'll find something like this</p>
<pre><code>public bool CanDoSomething { get { return someCondition; } }
public void DoSomething()
{
// execute stuff here
}
</code></pre>
<p>Then throughout your view model you will then find </p>
<pre><code>NotifyChanged(() =&gt; CanDoSomething);
</code></pre>
<p>anywhere there's code that could change the result of the CanExecute condition.</p>
<h3>So what's wrong with all this?</h3>
<p>As I mentioned earlier, this is all workable for simple scenarios but gets unwieldy pretty quickly as screen complexity/number of commands increases. I've come into code bases for complex WPF applications that have used this style of commands and it isn't fun, with ViewModels having blown out to thousands of lines of tangled code. </p>
<h3>Embrace the commands</h3>
<p>So my advice, embrace the commands. Abstract the command functionality away from the ViewModel code and write command objects.</p>
<p>Also, decouple the ViewModel and the Command implementation. Commands that take a "parent" ViewModel in their constructor and wire themselves to events (think PropertyChanged, ObservableCollection.CollectionChanged etc) will lead to trouble and be hard to test. I've had much better results through decoupling using an EventAggregator. I'll save further discussion on decoupling and EventAggretion for another time. </p>
</content></entry></feed>