Creating FileNodes

Follow the instructions in Getting Started first. You should have a Lightswitch application and you should have added this data source extension to your Lightswitch application.

IMPORTANT - If you are updating from a previous version, update the data source (by right-clicking on the SQLFileTable data source under Data Sources in your Server project, and choosing Update datasource from the context menu). You must do this when upgrading the data source extension in order to implement the latest code changes in your project. For example, some fields are now hidden by default, and you can now specify your own FileNode.ID where you could not do this in the first few releases. If you don't update your data source, you won't get these changes.

This example shows how to build a Silverlight screen to create new FileNodes, representing either a file or a folder in the SQL Server FileTable.

Building the screen

  1. Change the summary property of FileNode to the Path property (showing the entire path from the root of the FileTable down to the exact file or folder). This is useful for listing multiple levels of hierarchy alongside one another. To do this:
    1. Double-click FileNodes.lsml underneath your SqlFileTable data source in the Server project.
    2. Choose the DesktopClient perspective from the list of perspectives at the bottom of the designer window.
    3. Choose Path in the Summary Property of the property grid (typically bottom-right corner of your screen). From here on out, any time a FileNode is shown in a list or as a summary, the text displayed will be the full path down the actual file or folder.
  2. Add a screen to your DesktopClient project. In the Add New Screen dialog, select New Data Screen as the screen template, and select the FileNode in your project as the ScreenData. The resulting screen name would typically be CreateNewFileNode - which is fine for our purposes.
  3. In the default screen, remove the following properties (just select them in the RowsLayout and hit Delete - this will only leave Name and Is Folder):
    • File Type
    • Path
    • Size
    • Data
  4. You're going to want to select a folder to create things in. Add the GetFolders query to your screen. To do this:
    1. Select Add Data Item... at the top of the screen designer window
    2. In the Add Data Item dialog, choose Query, then choose the GetFolders query
    3. Click OK
  5. You will need to give users a way to pick a target folder in which to create things. To show the results of the GetFolders query on your screen:
    1. Select Add at the very bottom of the screen designer window (underneath the RowsLayout that contains the Name and Is Folder fields, right now)
    2. Select New Group
    3. Change the type of the group to a Group Box
    4. Change the name of the group box to CreateInFolder (note: this will set the Display Name to Create In Folder automatically)
    5. Drag the GetFolders query out of the list of data items at the left side of the designer screen, underneath the new Group Box. If you do this right, it will add a Path Locator text box, and Include Subfolders check box, and a Get Folders data grid to the Group Box.
    6. Get rid of (delete) the Path Locator text box; you won't be needing it (note - setting this to a specific PathLocator would limit the list of folders returned by the GetFolders query to only those folders at and below the specified PathLocator).
    7. Change the Data Grid to a List. This will replace the individual fields inside the Data Grid with a summary of the folders returned by the GetFolders query (incidentally - this is why we set the Summary property to Path earlier).
    8. Change the name of the List from GetFolders to TargetFolder (since this is how your user will pick a target folder).
    9. Disable Export to Excel (check box in the Properties) of the TargetFolder list (this is probably something your user would not want to do here anyway).
    10. Remove the Add, Edit, and Delete buttons from the TargetFolder list's Command Bar (this would not be the place to do that).
  6. You want to list all folders as potential target folders. Passing a null value to the GetFolders query for the PathLocator parameter does this (returns everything). To allow a null value for that parameter, you need to set Is Required to false for the corresponding property. Select the PathLocator property in the screen designer's data item list (this will be the instance of PathLocator that looks like it has a box next to it), and uncheck Is Required at the bottom of the Properties window.

Writing the code

You will want to give your users a way to just pick a file. To do this:
  • Add a button to the Screen Command Bar. Call it SelectFile (type this name in the text box under the "Write my own method:" radio button). Click OK.
  • To ensure that only people who could create files use this button, right click on the new button, choose Edit CanExecute Code from the context menu, and add this code (note - SqlFileTableData may or may not be the name of your data source - by default, it would be named SqlFileTableDataSourceData - but that seemed redundant to me, so I changed it when I attached to the data source):
        partial void SelectFile_CanExecute(ref bool result)
        {
            // Write your code here.
            result = this.DataWorkspace.SqlFileTableData.FileNodes.CanInsert;
        }

  • To actually select a file, you need to show a standard OpenFile dialog, and if the user picks a file, take appropriate actions. Right click on the SelectFile button in the Screen Command Bar, choose Edit Execute Code from the context menu, and make the following changes:
    • Add this to the using statements at the top of the code page:
using System.Windows.Controls;
using Microsoft.LightSwitch.Threading;
  • Add this to the code for the SelectFile_Execute() method:
        partial void SelectFile_Execute()
        {
            // Write your code here.
            Dispatchers.Main.Invoke(() =>
            {
                var dlg = new OpenFileDialog();
                if (dlg.ShowDialog() == true)
                {
                    // You can give a new item a Guid that you assign and keep track of elsewhere
                    // (for example, in an associated database table "DocumentId" property)
                    Guid nodeId = Guid.NewGuid();
                    this.FileNodeProperty.ID = nodeId;

                    // Populate Data
                    this.FileNodeProperty.Data = File.ReadAllBytes(dlg.File.FullName);

                    // Indicate the original name of the file (user may change if desired)
                    this.FileNodeProperty.Name = dlg.File.Name;

                    // Indicate that this is not a folder
                    this.FileNodeProperty.IsFolder = false;
                }
            });

        }


You will want to create any new FileNode in the folder that the user selected. To do this, you need to set the ParentPathLocator property of the newly-created FileNode to the PathLocator property of the FileNode representing the folder in which you want to create the new FileNode. To do this:
  • Choose the GetFolders query in the list of data items on the left hand side of the designer window
  • Click on < >Write Code at the top of the designer window
  • Under Collection Methods, choose GetFolders_SelectionChanged
  • Add this code to the GetFolders_SelectionChanged method:
        partial void GetFolders_SelectionChanged()
        {
            if (GetFolders.SelectedItem != null)
            {
                this.FileNodeProperty.ParentPathLocator = GetFolders.SelectedItem.PathLocator;
            }
        }


Finally: If your user chooses Is Folder and also selects a file, something has to win. A FileNode can't both be a folder, and contain data. You need to decide which choice you're going to respect. For this example, if the user selects IsFolder, we respect that choice, and remove the Data from the new FileNode before it gets created on the server (if we didn't, an exception would result when we attempt to insert the new FileNode, because the database won't allow Folders to contain their own data). To make this change:
  • Click on < >Write Code at the top of the designer window
  • Under General Methods, choose CreateNewFileNode_Saving (runs on the client, just before screen data is saved)
  • Add this code to the CreateNewFileNode_Saving method:
        partial void CreateNewFileNode_Saving(ref bool handled)
        {
            // Write your code here.
            if (this.FileNodeProperty.IsFolder)
            {
                this.FileNodeProperty.Data = null;
            }
        }


That's it. Compile and run the application. You will see that:
  • You can select a file location from a list of folders
  • If you check "Include Subfolders" - your list of potential target folders includes every folder in the FileTable
  • You can search for a folder in which to create your new FileNode (using the Search box at the top of the list)
  • You can select a file to upload, using a standard OpenFile dialog box (right out of the operating system)
  • If you check the box indicating that a FileNode is a folder - regardless of anything else - it is treated as a folder
  • You will still get an error from the server if you attempt to upload a file of the same name to the same location in the FileTable, using this creation screen

Yes - you could overwrite an existing file. But that's a tutorial for another day.

Last edited May 30, 2014 at 11:30 PM by DonYeske, version 2