Connecting UWP Emulator to IISExpress localhost

I’m sure this has been covered a lot, but I’m writing it down so I don’t forget how I did it. If it helps anyone else then great.

1. Locate IIS Express in the system tray

image

2. Select Show All Application in IIS Express, and select your site in the list

image

3. Click on the link in the Config section

Find your site, duplicate the localhost binding element and replace localhost with the IP Address of your machine;

                    
                    

4. With IIS Express tool stop all sites and then re-run your site. NOTE YOU MUST BE RUNNING as Administrator, only admin can allow IIS Express to bind to a non-localhost address

Your emulators should now be able to access the site using your machine’s IP Address.

I’ve found a much nicer explanation Accessing an IIS Express site from a remote computer

How to debug Continuum?

Developing for Continuum poses an initially thorny question, “my phone is plugged into the dock, how can I also plug it into my PC to debug?”. My recommendation is to get yourself a Miracast device and use Continuum’s wireless connection feature. That way your phone can be plugged into your PC for debugging while casting a Continuum desktop to your monitor. If you really need a keyboard and mouse then they’ll have to be wireless too, but the phone’s virtual trackpad and keyboard are enough to get by.

Element to support changing focus in MVVM

The other day I moaned that setting focus to a control in an MVVM environment felt like a painful disconnect. There are probably a dozen ways to resolve this issue, but I thought I’d try to use a method that at least isn’t a Behaviour.

Consider the following snippet of XAML

   <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <local:FocusManagerElement ControlName="{Binding SuggestedFocusName}" />
        <StackPanel>
            <TextBox x:Name="Barny" />
            <TextBox x:Name="Fred" />
            <TextBox x:Name="Bert" />
            <Button Content="Test" Tapped="Button_Tapped" />
        </StackPanel>
    </Grid>

The idea is that the FocusManagerElement is bound to the current view model and will set focus to whatever control is named by the View Model via the SuggestedFocusName property. When the logic in the View Model changes and we want to change the focus the we can simply update that property.

    public class TestViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        private string suggestedFocusName;
        public string SuggestedFocusName
        {
            get { return this.suggestedFocusName; }

            set
            {
                if (this.suggestedFocusName != value)
                {
                    this.suggestedFocusName = value;
                    if (PropertyChanged != null)
                    {
                        PropertyChanged.Invoke(this, new PropertyChangedEventArgs("SuggestedFocusName"));
                    }
                }
            }
        }

        public void DoWork()
        {
            // do some logic that means we need to change the focus
            this.SuggestedFocusName = "Fred";
        }
    }

From a developers point of view I think that’s pretty easy and flexible to use. All that remains is to show the implementation of the Focus Manager Element itself;

namespace AppFocusManager
{
    using Windows.UI.Xaml;
    using Windows.UI.Xaml.Controls;

    /// <summary>
    /// Element to support setting the focus via a bindable object
    /// </summary>
    public class FocusManagerElement : FrameworkElement
    {
        // Using a DependencyProperty as the backing store for ControlName. 
        public static readonly DependencyProperty ControlNameProperty =
            DependencyProperty.Register("ControlName", typeof(string), typeof(FocusManagerElement), new PropertyMetadata(null, new PropertyChangedCallback(ControlNamePropertyChanged)));

        /// <summary>
        /// Name of control to set focus to
        /// </summary>
        public string ControlName
        {
            get { return (string)GetValue(ControlNameProperty); }
            set { SetValue(ControlNameProperty, value); }
        }

        /// <summary>
        /// Control Name has changed
        /// </summary>
        /// <param name="dependencyObject">the instance of FocusManagerElement</param>
        /// <param name="eventArgs">new name of control to set focus to</param>
        private static void ControlNamePropertyChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs eventArgs)
        {
            var focusManagerElement = dependencyObject as FocusManagerElement;
            var controlName = eventArgs.NewValue as string;
            if (!string.IsNullOrEmpty(controlName))
            {
                var elementToFocusOn = focusManagerElement.FindName(controlName) as Control;
                if (elementToFocusOn != null)
                {
                    elementToFocusOn.Focus(FocusState.Programmatic);
                }
            }
        }
    }
}

Read and Edit OpenXml Docs (Word, Excel, etc.) in Windows 10 with c#

It is often useful to be able examine and edit Microsoft Office Documents in your own applications. Office Documents have being using the OpenXml format for some time now, in this post I’ll demonstrate how you can read and manipulate the data.

NB For more information, and to download some great tools including the Open , visit http://openxmldeveloper.org/

 

Reading data from Excel

NB For some reason you CANNOT use any other code to read a document if the document is already open in an Office Product, in this case Excel. If you get AccessDenied then check the document isn’t already open.

Consider the following spread-sheet;

image

I’ve saved this document as Book1.xlsx. If you haven’t downloaded the Open XML SDK 2.5 for Microsoft Office tools then rename the document to Book1.zip and open the Zip. I am not going to go into great depth about how the document packaging works, see the open xml developer site for more information. But basically each document is a Zip file containing a content catalogue and folders with the data represented in the document. So to examine the data in the first sheet you will find that located at; xl/worksheets/sheet1.xml

The first step is to open the document;

            FileOpenPicker opener = new FileOpenPicker();
            opener.ViewMode = PickerViewMode.Thumbnail;            
            opener.FileTypeFilter.Add(".xlsx");

            
            StorageFile file = await opener.PickSingleFileAsync();
            if (file != null)
            {
                XmlDocument worksheet = null;
                using (var fileStream = await file.OpenReadAsync())
                {
                    using (ZipArchive archive = new ZipArchive(fileStream.AsStream(), ZipArchiveMode.Read))
                    {
                        worksheet = this.GetSheet(archive, "sheet1");
                    }
                }
            }

You can see that we’ve opened the document as a Zip Archive, now we can read the specific sheet file held within, in this case I’m storing the result in an XmlDocument, this is just my choice of Xml parser;

        private XmlDocument GetSheet(ZipArchive archive, string sheetName)
        {
            XmlDocument sheet = new XmlDocument();
            ZipArchiveEntry archiveEntry = archive.GetEntry("xl/worksheets/" + sheetName + ".xml");

            using (var archiveEntryStream = archiveEntry.Open())
            {
                using (StreamReader reader = new StreamReader(archiveEntryStream))
                {
                    string xml = reader.ReadToEnd();
                    sheet.LoadXml(xml);
                }
            }

            return sheet;
        }

Now we have the document, we can grab a value, here via XPath

       private string ReadCell(XmlDocument worksheet, string cellAddress)
        {
            string value = string.Empty;           
            XmlElement row = worksheet.SelectSingleNodeNS("//x:c[@r='" + cellAddress + "']", "xmlns:x=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\"") as XmlElement;
            if (row != null)
            {
                value = row.InnerText;
            }
            
            return value;
        }

There you have it, you’ve read the data in cell B2.

Writing data in Excel

Let’s now change that value from 2 to 99.

using (var fileStream = await file.OpenStreamForWriteAsync())
                {
                    using (ZipArchive archive = new ZipArchive(fileStream, ZipArchiveMode.Update))
                    {
                        await WriteCell(archive, worksheet, "sheet1", "B2", "99");
                    }
                }

In this example I’ve chosen to simply remove the sheet from the archive and put a new version back.

        private async Task WriteCell(ZipArchive archive, XmlDocument worksheet, string sheetName, string cellAddress, string value)
        {            
            XmlElement row = worksheet.SelectSingleNodeNS("//x:c[@r='" + cellAddress + "']/x:v", "xmlns:x=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\"") as XmlElement;
            if (row != null)
            {
                row.InnerText = value;
            }

            string sheetFilename = "xl/worksheets/" + sheetName + ".xml";
            ZipArchiveEntry archiveEntry = archive.GetEntry(sheetFilename);
            archiveEntry.Delete();

            archiveEntry = archive.CreateEntry(sheetFilename);
            using (var archiveEntryStream = archiveEntry.Open())
            {
                using (DataWriter writer = new DataWriter(archiveEntryStream.AsOutputStream()))
                {
                    writer.WriteString(worksheet.GetXml());

                    await writer.StoreAsync();
                    await writer.FlushAsync();
                    writer.DetachStream();
                }               
            }
        }

Let’s open the file in Excel and check our result;

 

image

Looks good.

 

What else can you do?

We’ve seen a simple example of reading and writing to Excel. But these basic techniques allow you to do pretty much anything with any Office document. The underlying schema was developed to aid the use of tools, so anything is possible. Again I would point to Open XML SDK 2.5 for Microsoft Office and http://openxmldeveloper.org/ for information about how to interpret the various document types. My recommendation is to write an example document and use the SDK tools to learn how to reproduce it.