Tech in the 603, The Granite State Hacker

v.Next Enterprise (You & Kroger)

krogerI ran across this article from Forbes on LinkedIn.  It’s an interesting bit about how Kroger is reacting to the threat that Amazon/Whole Foods suddenly represents in its market segment.

https://www.forbes.com/sites/andyswan/2018/08/14/kroger-fighting-back-amazon-whole-foods/#543edd285ce6

The Amazon/Whole Foods merger represents a heavily modernized re-make of a traditional business, and it is expected to put grave pressure on the rest of the grocery segment.

If your market segment isn’t feeling this kind of pressure already, you likely will be soon.

Your business has only a couple of choices when it comes to modernization.

  1. React to the pressure that your market segment is under already.
  2. Begin preemptively, and be the pressure the rest of your market segment feels going forward.

I remember the days of building “nextgen” software.  That model has scoped up a few times, to vNext services, to next gen infrastructure / cloud, to vNext IT division.

Either way, it’s time to start developing your company’s “nextgen enterprise” strategy.

 

 

Tech in the 603, The Granite State Hacker

Need to Synchronize Columns of a Master/Detail Grid in DevEx WPF?

I generally prefer Telerik controls, but I’ve got a client that uses Developer Express.  I recently had a need to synchronize columns in a Developer Express WPF Master/Detail grid.   It’s a bit of an unusual circumstance, where we have Master / Detail records that use the same view interface, but found the TreeListControl unable to scale up to the demands of our use cases.  The client still wanted the detail grid’s columns to appear to functionally be the same column as the master record’s (with the ability to show/hide the detail).

Thankfully, the Dev Express GridColumn class is a DependencyObject, and all the needed properties are exposed as DependencyProperty’s.

Since the detail grid has the same data interface as the master grid, I was even able to clone the column definitions. 

Finally, since this was an MVVM project, I didn’t want the functionality in code-behind, so I abstracted the code for this into a Behavior.

The approach was to bind the Width, Visibility, and VisibleIndex properties of each master grid column to a cloned detail grid column, giving the two entities the appearance of being one functional entity.
Here’s the snippet representing the detail grid definition….



        <dxg:GridControl>

          <dxg:GridControl.DetailDescriptor>


                <dxg:DataControlDetailDescriptor ItemsSourceBinding="{Binding Details}">


                    <dxg:GridControl x:Name="DetailsGrid" AutoGenerateColumns="None" ColumnsSource="{StaticResource ColumnsCollection}" >


                        <dxg:GridControl.View    >




                            <dxg:TableView  AutoWidth="False"


                            AllowCascadeUpdate="False"


                            AllowFixedGroups="True"

                            ShowGroupPanel="False"

                            CellStyle="{StaticResourceDefaultCellStyle}"

                            NavigationStyle="Row"

                            ShowGroupedColumns="True"

                            AllowGrouping="True"

                            AllowEditing="False"

                            AllowScrollAnimation="False"

                            ShowFixedTotalSummary="False"

                            AllowHorizontalScrollingVirtualization="True"

                            HorizontalScrollbarVisibility="Auto"

                            RowStyle="{StaticResource RowStyle}"

                            AlternateRowBackground="{x:Static dxRes:DevExpressResources.AlternateRowBackgroundBrush}"

                            UseLightweightTemplates="None"

                            ShowColumnHeaders="False"

                               />

                        </dxg:GridControl.View>

                        <i:Interaction.Behaviors>


                            <local:SyncDetailGridColumnsBehavior/>


                        </i:Interaction.Behaviors>

                    </dxg:GridControl>

                </dxg:DataControlDetailDescriptor>

            </dxg:GridControl.DetailDescriptor>

        </dxg:GridControl>



Note the highlighted part above that introduces a local class called SyncDetailGridColumsBehavior, shown in its entirety below:

using System.Windows.Data;

using System.Windows.Interactivity;

using DevExpress.Xpf.Grid;


namespace Local
{
    public class SyncDetailGridColumnsBehavior : Behavior<GridControl>
    {
        private GridColumnCollection_parentGridColumns;
        private GridColumnCollection_detailsGridColumns;
        protected override void OnAttached()
        {
            _detailsGridColumns = AssociatedObject.Columns;
            _parentGridColumns = AssociatedObject.ResolveParentColumnCollection();
            InitializeMasterDetailGrid();
        }
       
        private void InitializeMasterDetailGrid()
        {
            _detailsGridColumns.CloneColumnsAndBindWidthsFrom(_parentGridColumns);
        }
    }
    internal static class ColumnHelpers
    {
        public static GridColumnCollectionResolveParentColumnCollection(this GridControl associatedObject)
        {
            var result =
                ((DevExpress.Xpf.Grid.GridControl)
                    ((System.Windows.FrameworkContentElement) associatedObject.Parent).Parent).Columns;
            return result;
        }
        public static voidCloneColumnsAndBindWidthsFrom(this GridColumnCollection targetGridColumns,
            GridColumnCollection sourceGrid)
        {
            targetGridColumns.Clear();
            foreach (var aSourceColumn in sourceGrid)
            {
                var aClonedColumn = aSourceColumn.Clone();
                aSourceColumn.BindWidths(aClonedColumn);
                aSourceColumn.BindPositions(aClonedColumn);
                targetGridColumns.Add(aClonedColumn);
            }
        }
        public static GridColumn Clone(this GridColumn source)
        {
            return new GridColumn()
            {
                Name = source.Name,
                Width = source.Width,
                Binding = source.Binding,
                Header = source.Header,
                Style = source.Style,
                CellStyle = source.CellStyle,
                CellTemplateSelector = source.CellTemplateSelector,
                CellTemplate = source.CellTemplate,
               
            };
        }
        public static void BindWidths(this GridColumn source, GridColumn bindingPartner)
        {
            source.SetBinding(BaseColumn.WidthProperty,
                new Binding(“ActualWidth”)
                {
                    Source = bindingPartner,
                    Mode = BindingMode.OneWay,
                    UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
                });
            bindingPartner.SetBinding(BaseColumn.WidthProperty,
                new Binding(“ActualWidth”)
                {
                    Source = source,
                    Mode = BindingMode.OneWay,
                    UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
                });
        }
        public static void BindPositions(this GridColumn source, GridColumn bindingPartner)
        {
            source.SetBinding(BaseColumn.VisibleIndexProperty,
                new Binding(“VisibleIndex”)
                {
                    Source = bindingPartner,
                    Mode = BindingMode.TwoWay,
                    UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
                });
           
        }
        public static void BindVisibility(this GridColumn source, GridColumn bindingPartner)
        {
            source.SetBinding(BaseColumn.VisibleProperty,
                new Binding(“Visible”)
                {
                    Source = bindingPartner,
                    Mode = BindingMode.TwoWay,
                    UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
                });
        }
    }
}
       

I expect this to cover 90% of our needs, the other 10% has to do with row selection across master/detail boundaries, but that’s a story for another day.

In the meantime, let me know how this makes ya feel…  leave a comment, below.

Thanks!

Tech in the 603, The Granite State Hacker

Time to Extend Your Brand to Windows 10

Marketers, if you’re looking for fresh, fertile ground to extend your brand into, jump now on Windows 10.

The Windows 10 app store is a clear path to:

  • Bump up your online store shopper counts
  • Extend ever-available services directly to your Windows customers (which is about 90% of them)
  • Connect with your brand’s demographic in a way that helps you better understand their needs
  • Build brand value by connecting with partners
  • Build brand value by connecting with social media
  • Escape web browser inconsistency that threatens to pull brand value down
  • Escape security/stability issues in popular platforms (e.g. Android) that threatens brand value.
  • Reach more device form factors with a single, less specialized (less expensive) codebase (desktop, tablet, phone, even game consoles and devices)

AND…

Windows 10 is attracting Microsoft’s (and, by extension, arguably) consumer tech’s most valuable territory,

To wrap one’s head around this, it helps to understand recent history a bit. 

Being a “convicted monopoly” put a lot of costly restrictions on Microsoft, and especially Windows, making every OS release from XP to Vista to Windows 7 less than it could have been.  Despite the fact that Windows is still king in the desktop arena by far, Microsoft has done a great job of digging out from under the perception that it has a monopoly in that space.  It dug itself out by connecting Windows to the both to the cloud and to the broader computing device market, including tablets, smartphones, consoles and devices.

Being out from under those restrictions has enabled Microsoft to really make Windows 10 come together in ways that even the incumbent Windows 7 couldn’t.   All indications are that Windows 10 is a hit and will de-throne Windows 7 as the de-facto desktop OS within a couple years. Between re-claimed freedom to innovate, lessons learned, and other market conditions, it’s a no-brainer that Windows 10 has legs.

[Here’s a number to associate with Windows 10:  1 Billion UPGRADES.  (not counting the number of devices that will be sold with Windows 10 on them.)]

What about Social Media?  According to folks like @fondalo:

With nearly 62% of consumers stating that social media has “no influence at all” on their purchasing decisions (Gallup), marketers are faced with substantial hurdles in an ever-increasingly noisy digital landscape. This challenge is further amplified by a CMO Council study showing that only 5 percent of brands feel they are extremely effective at creating experiences that resonate with target audiences.

In fact, most marketers are currently forced to put more resources toward their digital and social efforts, just to maintain their current returns. I believe this gap will continue to widen for larger brands, but smaller more nimble retailers that get creative and deploy proper resources could end up being the big winner.

Finally, it goes without saying that it no longer matters that you’ve extended your brand to iOS (iPhone/iPad) and/or Android.  The app marketplace for those devices, in your space, is saturated… even super-saturated.  You’ve extended your brand to those app stores, and so has every other brand in the world, including all your competitors.   Of course, saturation will occur in the Windows 10 app marketplace, but getting in ahead of the crowd has its advantages.

Never mind the upside potential on phones and tablets (which remains huge, and far more addressable from Windows 10).  The pendulum is swinging back to the desktop/laptop again (for now).

Being a Microsoft appointed Technical Solutions Professional, I can help.  Let me know how I can bring my (and my team, BlueMetal‘s) expertise to bear for you in your goal to make the jump.
In any case, talk to me.  If you’re a marketing technology manager, what do you see as the pros and cons of jumping into the Windows app pool?  
Tech in the 603, The Granite State Hacker

Data Persistence in Windows Universal (8.1) apps (Boston Code Camp 23)

Thanks to everyone who joined me for my Boston Code Camp 23 presentation.  Shuffling data around is a core responsibility of any serious computing platform.  Windows Universal really goes above and beyond the mundane call of duty with consistency and utility. It’s part of what makes the Windows client platform a true “cloud car”, especially with its Backup, Roaming Settings / Folders, and Roaming Password Vault capabilities as native functionality… all from the Windows.Storage namespace.

Here are

For the individual who asked what encryption level the Windows Password Vault functionality uses, I looked it up, and it’s 128bit AES encryption.  Stern stuff there.

Another question came up about app backups.  As I said in the presentation, the content of the Local storage is backed up automatically to the cloud by the OS.  (Isn’t that fantastic?!)

Likewise, as mentioned, the Temporary storage is excluded from backups.

One detail I missed however… the LocalCache storage area.  LocalCache is like Local except that it is not backed up.  LocalCache differs from Temporary storage in that the OS will not wipe it as it occasionally does the Temporary storage.  Next time I do this presentation, I’ll make sure to update it to discuss LocalCache.

Here’s a comparison of the storage options available to developers in the 8.1/universal platform. Note that each user on a device gets their own app-specific sandbox *and* OneDrive space for each installed app.

Type Availability Limits Settings hashtable Backed Up By OS Sync’d to all App / User / Devices by OS Encryption Wiped By OS if space is low Uri prefix Suggested use
Install Package Universal Static/ReadOnly Media from Install No No No Sandboxed No ms-appx:// Version specific static app media
Local Universal Available free storage Yes Yes No Sandboxed No ms-appdata:///local/ General
Local Cache Windows Phone Only Available free storage Yes No No Sandboxed No   Persistent cache
Temporary Universal Available free storage Yes No No Sandboxed Yes ms-appdata:///temp Semi-persistent cache
SD/Removable Universal Available free storage No No No None No   Removable/general
Roaming Universal 100k Yes (by virtue of roaming) Yes Cloud Partitioned No ms-appdata:///roaming Roaming settings
Password Vault Universal 100k (included in Roaming) Password-friendly structure (by virtue of roaming) Yes Cloud Partioned + 128bit AES No   Roaming credentials /OAuth tokens

I asked my stunt audience (the kids) later what my presentation had been about.  I was glad to know at least one of them had gotten it right. 

They were inspired, though, and that’s the important part. 

I hope you found inspiration in technology from both the day and maybe in some small part from my presentation.

Tech in the 603, The Granite State Hacker

Lumia Problems

I’m a pretty serious fan of Windows Phone, and especially Lumia devices.   In addition to the NH Windows Phone Users Group (now Granite State Windows Platform App Devs),  I’ve convinced everyone in my immediate family, and a good chunk of my extended family to go Lumia… 

So it breaks my heart when I see a Windows Phone that’s gone awry.  Among the many I’ve come in contact with, I’ve seen one or two develop issues that seem outside of normal hardware wear & tear.

My own device has occasionally had trouble with its SD card, occasionally forcing a restore.   These are annoyances to me, Windows Phone is a cloud car, so resetting the device and getting it back to normal is really only a mater of re-entering credentials, and the phone’s back in business.   The restore tends to re-apply start-screen layout and the set of installed apps on the device… the apps themselves are responsible for their individual recoveries, typically from their own cloud backups.   The few times I’ve been forced to do a full hard reset & restore, it’s been an ordeal that typically lasted under an hour (with a good Wifi connection).

This past week, I think the SD card flaked out again, but restoring from a backup didn’t resolve the issues.   I identified a number of odd behaviors, and was almost convinced my device was beyond recovery:

  • Power button:  the typical short-click which should toggle the device in & out of standby mode simply was not operating.   Long clicks, intended to shut the device down completely, were working, so… not a hardware disconnect.   In order to wake the phone up, I had to plug in a power source… and then had to wait for it to put itself to sleep.
  • App updates:  app updates were identified and the device would queue them, but rather than automatically downloading and installing, they’d hang in the download queue, all marked as Pending.  Occasionally one would come up with an error, but a retry would simply hang it back in Pending state.
  • WiFi internet sharing would not allow clients to connect.
  • Power saver:  on a whim, I put the device in power saver mode.  At first, it wouldn’t take the change.  Then I told it to always go in powersaver mode, and then, ironically, I couldn’t get it OUT of power saver mode.
  • Data Sense:  the app would crash and abend when trying to open it.
  • Mail sync:  would only sync manually
  • Alarm:  I missed my usual bus twice this week because my alarm failed & I overslept.

The end solution:  hard reset, but don’t restore from a backup…  just manually set up your accounts and re-download apps.  It took me a couple hours, but to get my 1520 back on track again, it was well worth the time.  In retrospect, I’m also happier because I didn’t re-install a ton of apps that I don’t use anymore, so the device is much leaner.  

The Windows Phone platform is relatively mature… it doesn’t fail often, but I think I’m going to have to pick up a better SD card.  The hard part is that I think I’ve heard rumors of some of these symptoms on devices that don’t have SD card slots.

My understanding is that it has something to do with the Cyan firmware update.  The Denim firmware may provide more stability, and that update started rolling out to devices in December with a promise that by the end of that month, it would be rolled out to the full Lumia nation.  We’re pushing into Feb 2015, and most in the US are still waiting.

[Addendum, 5/7/2015]:  My Lumia 1520 had a relapse of the above symptoms on Windows Phone 8.1.1 / Denim.   On a whim, I decided to try upgrading to the Windows 10 Insider Preview.  The problems with the SD card intensified as well.  I finally bit the bullet and replaced the SD card.  I did have to hard reset the phone back to the “stock” Windows 10 Insider Preview, but after that, not only were all the above symptoms resolved, but another long running annoyance…  a problem I thought to be related to the Lumia 1520 itself, went away.  The problem…  often, entering the unlock code, number presses would repeat so quickly that the phone would fail to unlock.  Occasionally it was bad enough to lock my phone for a minute or two.    Again, this issue is now resolved along with the other symptoms I noted in this post by replacing the SD card with a new one.

Tech in the 603, The Granite State Hacker

AppStudio gotcha

Recently, I upgraded the Granite State (NH) SharePoint Users Group’s website from WSS 3 (MOSS 2007 generation) to SharePoint Foundation 2013.  The upgrade itself went as well as a 2007 to 2010 to 2013 upgrade could go, in general.

The only real “problem” I ran into was the Windows Phone app I wrote for the group years ago.  It was coming up with a 401 error trying to grab content from lists.asmx.  

I spent some time digging in the dirt, trying to resolve the 401, and hit a few common settings known to have an impact, but no good.  

Rather than struggle with it in my not so copious amounts of spare time, I decided to trash the old app, and build a new one with AppStudio.  

The app loads content from the #NHSPUG web site (http://granitestatesharepoint.org), mostly via RSS feeds.  I put a little extra effort into this.  Using AppStudio (http://appstudio.windows.com), I found a couple hours…  after that, I had not only a much prettier v3 of the Windows Phone app, but a Windows 8.1 (tablet style) publishing package as well.

One thing that caught me off guard though… the Gotcha:

The Windows 8.1 edition of the app wouldn’t load the content from the users group website. 

With some debugging, I found that attempts to load the content were coming up with “Unable to connect to the remote server. hresult=   -2146233088”.

Turns out the error had to do with the fact that I had not enabled Capability “Private Networks (Client & Server” in the Package.appxmanifest.   Ironically, the app works fine anywhere except where I was trying to test it:  on the same network as the content source server. So, to be fair, this is an environmental/configuration issue, not AppStudio, but it was worth mentioning, since my original assumption led me down that path. Maybe this will help someone else.

Oh… Here’s the Windows Phone app:
http://www.windowsphone.com/s?appid=8c1ce3ea-9ffd-46a0-80bd-6b45d1019b32

And here’s the Windows 8.1 (tablet style) app:
http://apps.microsoft.com/windows/app/granite-state-sharepoint-users/01ea0a83-f3af-4be6-abb0-268587072686

And here’s my moment of shame recording the incident and solution in the forums:
https://social.msdn.microsoft.com/Forums/windowsapps/en-US/be7b02cf-25d0-4aa2-8850-e0e2dce21fd2/appstudio-windows-81-apps-not-loading-external-content?forum=wpappstudio&prof=required

Tech in the 603, The Granite State Hacker

Cobbler’s Shoes

Happy New Year! I hope you enjoyed the holidays!
 
I took time off for the holidays… not as much as I’d have liked to, but enough to enjoy it.

What’d I do?

The cobbler finally got a chance to tend to his own shoes, at least infrastructure wise.

A few years ago, I caught that MS was giving away a license to Windows System Center Core, and I realized I had enough retired hardware to cobble together a hobby-level host. I then did a Physical->Virtual on my small network of Windows 2003 based servers that I ran the NHSPUG website from.

The setup was nice, actually… all three virtual machines ran with room to spare on what was originally an old client-class PC. With dynamic RAM turned on and all three VMs cranking, they occasionally managed to consume nearly a third of the host’s 8GB of RAM.

Having recently had opportunity to get a hold of platform MSDN licensing, I upgraded my entire home network infrastructure by two platform generations across the board.

Seriously… Windows Server 2003 ->  2012 R2 64, SQL 2005 -> 2014, SharePoint WSS3 -> SharePoint Foundation 2013.

Almost all of it was build, replace, rip… build new VMs, integrate them into the domain, migrate data & config as needed, then shut down the systems they replace. The fun one was SharePoint WSS 3.0 upgrading to Foundation 2013. I had to bounce the content databases off a spare 2010 farm I had left over from a project at work. It was nice that it was possible to do that, given that the 2010 farm was a different domain. It’s amazing how much you can get done in short order when you are a one-man IT shop… the communications overhead savings alone is unreal.

The hard part is that newer software in the 64bit range uses much more system resources, so I have extended hosting not just to my System Center, but also to two Windows 8.1 Pro systems running Hyper-V, just to spread out the necessary load and provide some critical system redundancy.

With that, only obvious thing externally is that the Granite State NH SharePoint Users Group website ( http://www.granitestatesharepoint.org ) is now SharePoint 2013 based.

Internally, things generally seem a touch faster, smoother… maybe that’s just psychological, but I notice the difference, even if my wife & kids think it just functions as always, as expected.

I guess the irony in this is that my hobby infrastructure backlog is knocked down a few more notches than I thought I would ever get to… (yes, I took time off from work, and, to chill, I did some of what I do at work.) now my hobby development backlog has new possibilities and subsequently grown substantially.

One of the first things I’ve got to take care of is the few services the SharePoint upgrade has caused… the NHSPUG site still has some cosmetic issues I want to sort out. My Windows Phone apps that integrated with the WSS3 site are now broken, and I have some jiggering to do with my dev environment before I can even diagnose them. That doesn’t even cover some of the things I want to do with the NHWPAD group and my hobby/portfolio projects (e.g. Jimmy Sudoku).