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

Rise of the Smart App

Microsoft didn’t talk much about the Windows Phone at Build 2016.  If you think that’s news, you’re missing the point.

As Microsoft re-defines “Mobile First, Cloud First” they declare shenanigans on the idea that the tech world revolves around phone and tablet.  Yes, tablet and smartphone are mature, first-class citizens, now, but they’re not above laptops, PCs, or other computing devices, as Apple (and perhaps even Samsung) might have you believe.

There’s no denying that Microsoft lost the battle for smartphone market share.  RIM’s Blackberry, considered a relic of the primordial smartphone market, is all but forgotten. Microsoft was pushing Windows Phone as significant competitor, yet, with about the same market share as Blackberry, no one really took their smartphone offering seriously. 

Until Windows Phone’s recent convergence with the PC on the universal Windows 10 OS, Windows Phone had no more competitive edge than Blackberry, either.  Sadly, this new competitive edge comes too little, too late. Or has it?

Several years ago, in a very sly move, Apple narrowed and laser-focused the global technology mindset on a much smaller battle… one that it was well positioned in. Apple then equated the battle to the war… They made it all about the smartphone/tablet market.  (I don’t think Apple counted on Android, but it didn’t matter… in terms of market share, Android won, but in terms of profitability, Apple won.)  Billions of dollars can’t be wrong, so Microsoft tried to position itself in Apple’s vision, and let itself get dragged around for years… 

Until now.

By connecting Mobility with Portability, Microsoft is driving the scope of technology mindshare again, and are driving it back out to a scale Apple will have to struggle to position itself in. Apple made good smartphones.  Cool beans.

With its converged “Universal” Windows 10 platform, Xamarin portability, and mature cloud offerings replete with machine learning, Microsoft is targeting a much broader “smart app” market… Smart Apps are apps that make any device (keyboard, mouse, display/touchscreen, microphone, pen, scanner, camera, video recorder/editor, audio mixer, cell phone, media player, whiteboard, virtual/augmented reality, what have you) into a smart device.  (Notice anything missing here?  perhaps cars…  but it’s hard to imagine that won’t change in the next few years…  after all, cars (e.g. BMW) did get mentioned at Build.) 

The smartphone isn’t irrelevant, it’s just not the whole pie. The reality is that Microsoft is not going to exclude phones from Windows 10 now or any time soon. 

Smartphone prominence is not innovation superiority.

So, how does this make you feel?

Tech in the 603, The Granite State Hacker

Mobile First, Cloud First as Redefined in Build 2016

There were a number of very cool announcements made at Microsoft Build’s 2016 kickoff today, Wednesday, March 30th.  On first brush, one might not notice the common theme across the announcements, however.

These things may seem disconnected, but if you look again, they’re not… nor are the other less obviously connected major announcements such as:

Microsoft has been promising Mobile First, Cloud First for a long time. Until today, there’s been a consensus that Mobile First meant Tablet and Phone…  as in those hardware form factors get updates and features before classic alternatives.  Today Satya Nadella, CEO of Microsoft, addressed the developer crowd and clarified (or perhaps more accurately “redefined”) what “Mobile First” really means.

Mobile First, Cloud First has morphed to mean something more like “Portable First, Cloud First”, with portable referring directly to the Universal Windows Platform…  write your code once, and the user can take it to any device (desktop, laptop, phone, IoT) and use it as naturally as possible with the whatever human interface device is available (keyboard, mouse, touch, ink, voice, text, etc)…

And there is, indeed, how all the announcements fit together. 

All of the announcements made today talk about how Microsoft is diversifying the human interface, yet keeping the context of all your work and play available across all devices.  Your apps are there, and they work just as naturally with voice commands as they do with ink. 

Note that keyboard and mouse are relatively unnatural compromises in human interface paradigm, and their use will be diminished in the future. 

If pen and paper is the natural choice, Ink will replace it. 

If voice makes sense, it will be available.

If an intelligent actor might assist you, Cortana and your trusted “Network of Experts” (Apps and BotFX bots) are there. If a virtual or augmented reality makes sense, your apps will join you on Hololens. 

If an Xbox controller is the right choice, no problem. 

All of these things can be enhanced significantly with DirectX 12, even for non-games.

And the Cloud will interlink them naturally so that you can flip from tablet to Hololens without skipping a beat. (in some ways, live process migration is really becoming a reality;  when the apps are the same across every deployed device, the only thing that needs to transfer from device to device is user data, and that’s happening via cloud.)

One segment that didn’t see much love today:  the Web.  Or did it?  Bash for Windows 10 is a bit of a stretch to connect to the coming shift, but really, it is meant to make it easier for developers to deliver web-based, cloud-hosted solutions using Visual Studio to non-Windows hosts.  Indirectly this will aid in the creation of services that might support Bots made with the BotFX, for example.  All of this is based predominantly on JSON over REST / HTTP.

Some would point out that Windows 10 Mobile (formerly Windows Phone) didn’t get any stage time, either, but the reality is that Microsoft no longer sees the smartphone edition of Windows to be a separate thing.   Windows 10 is converging on “The Best Windows Ever”, Windows 10… smartphone or not. 

Tech in the 603, The Granite State Hacker

Tribute to the TI 80-something Graphing Calculators

Rummaging thru a box of stuff in storage, I ran across my old Texas Instruments TI-85 calculator.  I had to stop and fiddle it for a moment. I grabbed some AAA batteries, only to discover that the CR1616 backup had given up… the calculator operates like new, as in factor reset… but sadly, that means a game program I wrote for it 20 years ago was finally gone forever.

Back in the early 90’s, Exeter Area High School had an advanced math course that required a TI-81 calculator. I gladly used the course as an excuse to get my hands on this relatively expensive (near $100 in 1990 dollars) but amazing piece of hardware at the time.

In short order, I added its programming language to the list of languages I had already taught myself.  I loved using trigonometric functions to create pictures. I used to program it to do my trig and pre-calc homework for me. (In retrospect, my attempt at “cheating” was a hack that I learned more from than any lecture or textbook ever would teach me… you see, in order to program the calculator to do advanced math for me, I had to thoroughly understand it, myself.)

My own TI-85, which I upgraded to
for calculus at UNH. It’s a bit dusty today.
It cost about $100 when I
purchased it in the early 90’s.

The TI-8x calculators were my “gateway drug” to my love of mobile development.  I was already developing software for PCs, but I loved the challenges imposed by yet more limited footprints and hardware capabilities. 

I kept my TI with me to the point that my sister nicknamed it a “porta-geek”…  (There was even a girl who stole it from me, thinking to wound me for the fact that I wasn’t interested in dating her. It had no effect; I obliviously assumed I’d misplaced it in my own absent-mindedness. The story came out several years later, after I’d purchased a replacement.)

The term “porta-geek” is a term I still whimsically apply on occasion to my current daily driver mobile device, my Lumia 950XL running Windows 10.  My sister’s jibe didn’t phase me, either.

By coincidence, I was also in Target’s electronics department today. I was surprised to notice that they still had several 20+ year old TI-80-somethings…  but rather than the price being lower, the prices are actually higher.

A selection of same-generation TI calculators at Target today (3/20/2016).  Notice the TI-80-somethings still going for about $100+.

I can’t really say why 20+ year old calculators should still cost more than they originally did…  clearly normal technology market forces are not in effect for them.  My spidey-sense for socialistic-driven monopoly tingles.  I’m not the only one to have noticed the… discrepancy… over the past couple decades.  ( https://www.quora.com/Why-does-a-TI-83+-calculator-cost-the-same-as-it-did-12-years-ago )

That said, they were, and are great devices.

I’d love to see a Windows 10 emulator app made out of them….  maybe some day I’ll find enough spare time…  🙂

Tech in the 603, The Granite State Hacker

Intro to Rx.NET (Reactive Extensions)

Thanks to the gang for joining me at the Microsoft Store in Salem NH for my preso on “Intro to Rx.NET”   Being that it’s a toolkit I’ve been digging a lot at work lately, I had a feeling folks might appreciate a broad brush into to it.

Please check out the Granite State (NH) Windows Platform App Devs (#WPDevNH) on meetup.com to connect with the group and maybe even participate, yourself.  In addition to the core presentation topic, we had a great debate in speculation on how Microsoft’s purchase of Xamarin might settle out.  Also, I’ll be attending Build 2016, so we’re talking about having a special meeting early in April to recap and consider future presentations. (stay tuned!)

Rx reminds me a lot of other declarative language elements (XSL, XAML) in that it seems really natural, then you start looking at more advanced stuff and the complexity becomes boggling… then you start to really understand the abstractions and it feels natural again.

Without further ado, here’s my slides for the presentation:

[office src=”https://onedrive.live.com/embed?cid=90A564D76FC99F8F&resid=90A564D76FC99F8F%21824879&authkey=AC01r6jwJX5ng5M&em=2″ width=”402″ height=”327″]
I’d like to thank the folks at http://IntroToRx.com, I referenced them more than any other source putting this together.
Finally, for the code I demoed, please check out the post I mentioned, here:
Hope to see you soon!
-Jim Wilcox
The Granite State Hacker
Tech in the 603, The Granite State Hacker

Rate Limiting Events with the Reactive Extensions Rx

A fun little challenge that came up at work…  we have a stream of events that we publish / subscribe via a Reactive IObservable.   One of the things we’re testing for is swamping the subscribers with events for periods of time.  The tools in System.Reactive.Linq namespace include utilities like .Throttle(…), .Sample(…).  None of these supported our needs.

For our needs in this particular event stream, in this point in our stream, we can’t afford to drop events.  

Sample(…) picks off an item at various intervals, dropping the rest.  Throttle(…) sets up a window of time. It won’t release any object until there’s been a case where only one object was buffered in the given time window.  If you get another while the window’s open, the window widens to the original timespan.

Then there’s .Buffer(…) which can store event objects for a window, and then release them.  That amounts to releasing all the events in periodic bursts, but it’s not a rate limit.

Finally there’s the .Delay(…) method… which, ironically, delays publishing objects by an offset amount…  but that delays all objects by the same time offset.  If you have three events come in, 1 millisecond apart each, and put a 1 minute delay on them, they’ll enter the collection, and one minute later, will be published out… in a three-millisecond burst.

I want to be able to constrain my publisher such that I only want n number of entities per second. 

My solution separates the pub/sub.  It loads a queue with incoming events, and emits them immediately, up to the limit on the subscriber side. On the publisher side, it resets the counter and emits any overflow objects in the queue, also up to the limit.   

Yes, this model has problems, so address your risks appropriately… (“use at your own risk”).    You can run out of memory if the origin provides more items than the limiter is allowed to emit over long periods of time.

Anyway, here’s a Program.cs with the RxHelper extension RateLimit(…).  The program has a decent little before/after RateLimit(…).



using System;
using System.Collections.Concurrent;
using System.Reactive.Concurrency;
using System.Reactive.Disposables;

using System.Reactive.Linq;

 
namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {
 
            // simulate very fast (no delay) data feed
            var unThrottledFeed = GetFastObservableSequence();
 

            unThrottledFeed.Subscribe(Console.WriteLine);

            Console.WriteLine("That was an example of an event stream (with 100 events) only constrained by system resources.");

            Console.WriteLine();


            Console.WriteLine("Now rate-limiting at 10 items per second...\n");


            const int itemsPerSecond = 10;
 
            var throttledFeed = GetFastObservableSequence()
                    .RateLimit(itemsPerSecond);
 
 
            throttledFeed.Subscribe(Console.WriteLine);
 
            Console.WriteLine("END OF LINE");
            Console.WriteLine("Note that the Main() method would be done here, were it not for the ReadKey(), the RateLimit subscriber is scheduled.");
            Console.WriteLine();
            Console.WriteLine("Rate limited events will appear here:");
            Console.ReadKey(true);
 
 
        }
 
        #region Example Artifacts
        private static IObservable<TestClass> GetFastObservableSequence()
        {
            var counter = 0;
            var rnd = new Random();
            return Observable.Defer(() =>
                Observable.Return(0)
                    .Select(p =>;
                    {
                        counter++;
                        var x = new TestClass(30.0, counter);
                        x.Value += Math.Round(rnd.NextDouble(), 2);
                        return x;
                    })
                    .Repeat(100));
        }
 
        private class TestClass
        {
            public TestClass(double value, int instance)
            {
                Value = value;
                Instance = instance;
            }
            private int Instance { get; set; }
            public double Value { get; set; }
            public override string ToString()
            {
                return $"{Instance}: {Value}";
            }
        }
        #endregion
    }
 
 
   

    internal static class RxHelper
    {
        public static IObservable<TSource> RateLimit<TSource>(
            this IObservable<TSource> source,
            int itemsPerSecond,
            ISchedulerscheduler = null)
        {
            scheduler = scheduler ?? Scheduler.Default;
            var timeSpan = TimeSpan.FromSeconds(1);
            var itemsEmitted = 0L;
            return Observable.Create<TSource>(
                observer =>
                {
                    var buffer = new ConcurrentQueue<TSource>();
                    Action emit = delegate()
                    {
                        while (Interlocked.Read(ref itemsEmitted) < itemsPerSecond)
                        {
                            TSourceitem;
                            if (!buffer.TryDequeue(out item))
                                break;
                            observer.OnNext(item);
                            Interlocked.Increment(ref itemsEmitted);
                        }
                    };
                   
                    var sourceSub = source
                        .Subscribe(x =>
                        {
                            buffer.Enqueue(x);
                            emit();
                        });
                    var timer = Observable.Interval(timeSpan, scheduler)
                        .Subscribe(x =>
                        {
                            Interlocked.Exchange(ref itemsEmitted, 0);
                            emit();
                        }, observer.OnError, observer.OnCompleted);
                    return new CompositeDisposable(sourceSub, timer);
                });
        }
    }


}
 
 

Edit 1/27/2016:  Had to tweak RateLimiter(…) to immediately emit objects as long as it hadn’t hit it’s limit for the time span.  It always queues, just in case, to maintain order.

Tech in the 603, The Granite State Hacker

Retirement of the Corporate PC

Remember the company car?  Neither do I.   There’s a good chance the company-provided PC that most information workers are issued is trending toward extinction as well.

The net result could be a boon for PC retailers.  Policy agreements become SLA’s with the employee, and the budget moves out of IT and into HR.

Posted on Linked In:  Retirement of the Corporate PC

https://www.linkedin.com/pulse/retirement-corporate-pc-jim-wilcox

Tech in the 603, The Granite State Hacker

Live Process Migration

For years now, I’ve been watching Microsoft Windows evolve.  From a bit of a distance I’ve been watching the bigger picture unfold, and a number of details have led me to speculate on a particular feature that I think could be the next big thing in technology….   Live process migration.  

This is not the first time I’ve mused about the possibility… [A big feature I’d love to see in Windows 11] it’s just that as I work with tools across the spectrum of Microsoft’s tool chest, I’ve realized there are a few pieces I hadn’t really connected before, but they’re definitely a part of it.

What is live process migration?  Folks who work with virtual machines on a regular basis are often familiar with a fancy feature / operation known as live virtual machine migration….  VMWare’s vSphere product refers to the capability as vMotion.  It’s the ability to re-target a virtual machine instance, while it’s running… to move it from one host to another.

In sci-fi pseudo psycho-babble meta physio-medical terms, this might be akin to transitioning a person’s consciousness from one body to another, while they’re awake…  kinda wild stuff.

As you can imagine, live VM migration is a heavy duty operation… the guest machine must stay in sync across two host computers during the transition in order to seamlessly operate. For the average user, it’s hard to imagine practical applications. 

That said, live process migration is no small feat either.  A lot of things have to be put in place in order for it to work… but the practical applications are much easier to spot. 

Imagine watching a movie on Netflix on your Xbox (or maybe even your Hololens), but it’s time to roll.   No problem, with a simple flick gesture, and without missing a beat, the running Netflix app transitions to your tablet (or your phone), and you’re off.   Then you get to your vehicle, and your vehicle has a smart technology based media system in it that your tablet hands off the process to.   It could work for any process, but live streaming media is an easy scenario.

From a technical perspective, there’s a bunch of things required to make this work, especially across whole different classes of hardware…  but these problems are rapidly being solved by the universal nature of Windows 10 and Azure.

Commonality required:

  • Global Identity (e.g. Windows Live)
  • Centralized Application Configuration
    • Windows 10 apps natively and seamlessly store configuration data in the cloud
  • Binary compatibility
    • Universal apps are one deployable package that runs on everything from embedded devices to large desktops and everything in between.
  • Inter-nodal process synchronization
    • Nothing exemplifies this better than the 1st class remote debugging operation  in Visual Studio.  You can run an app on a phone or device from your laptop, hit breakpoints, and manipulate runtime state (local variables) from the laptop and watch the device react in real time.
  • Handoff protocol
    • I’m sure it exists, but I don’t have a good word to describe this, but it’s probably based on something like SIP
  • Runtime device capability checking (the part that sparked this blog post).
Over the years, there have been a lot of “write once, run anywhere” coding schemes.  Most involve writing a program and having the compiler sort out what works on each type of hardware…. what you get is a different flavor of the program for different kinds of hardware.  In Windows 10, it’s different.  In Windows 10, the developer codes for different device capabilities, and the application checks for the required hardware at run time.  
While the UWP does an amazing job of abstracting away the details, it puts some burden on the hardware at runtime…  the app developer has to write code to check, anyway: hey, is there a hardware camera shutter button in this machine?  If yes, don’t put a soft camera shutter button on the screen, but now the app has to check the hardware every time it runs.
I struggled a bit trying to understand this latter point…  why would Microsoft want it to work that way?  Except for a few plug & play scenarios, it could be optimized away at application install time…  unless your process can move to a different host computer/phone/console/tablet/VR gear.
While I am (more recently) a Microsoft V/TSP working for BlueMetal, an Insight company, I have no inside information on this topic.  I’m just looking at what’s on the table right now.   We’re almost there already.  Yesterday, I showed my son how to save a document to OneDrive, and within moments, pick up his Windows 10 phone and start editing the same document on it.
In my mind, there’s little doubt that Microsoft has been working its way up to this since Windows Phone 7… the only question in my mind is how many of these tri-annual Windows 10 updates will it be before “App-V Motion”-style live process migration is a practical reality.
Tech in the 603, The Granite State Hacker

Fix: Drag and Drop File Upload on Published SharePoint 2013 Pages

Ran into a long existing bug in SharePoint 2013 where you have a couple of conditions prevent uploading a file to a document library by drag & drop.

The conditions are these:

The document library is exposed as a webpart view on the page.
The page is a published page (as opposed to draft or checked-out) in a site where publishing is enabled at the site collection level.   (note that drag and drop uploads work if the page is not published.)

A number of posts describe the problem out on the interwebs, but I couldn’t find a single one with a working solution… 

They talked about dragdrop.js and the SP.Utilities.CommandBlock undefined error, and setting x-ua-compatible to IE9, and a few other pieces to the puzzle… 

After a consult with the gang around the BlueMetal office, we collectively arrived at the following solution, using Script On Demand functionality…

The fix is to add the following to a script block at the bottom of the master page associated with the published page:

  



     //Drag & Drop fix for publishing pages     
SP.SOD.executeFunc("sp.core.js");       
SP.SOD.executeFunc("cui.js");


That forces those libraries to load for your masterpage even if nothing else on the page requires them.

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?