From 1c036de8e527038f00b7ff07fc1ef4b80f23a846 Mon Sep 17 00:00:00 2001
From: Ian C <ianc@noddybox.co.uk>
Date: Wed, 27 Jun 2012 17:22:49 +0000
Subject: Started trying to add dependency objects.  Don't work yet.

---
 .../Converters/ConvertFolderFlag.cs                |  52 +++++++
 .../Noddybox.WindowsPhone.Silverlight.csproj       |   7 +-
 Noddybox.WindowsPhone.Silverlight/SaveDialog.xaml  |  62 ++++++--
 .../SaveDialog.xaml.cs                             |  97 +++++++++++++
 .../Themes/generic.xaml                            |  28 ++++
 .../ViewModels/FileDialogViewModel.cs              | 159 +++++++++++++++++++++
 Noddybox.WindowsPhone.Test/MainPage.xaml           |   5 +-
 7 files changed, 393 insertions(+), 17 deletions(-)
 create mode 100644 Noddybox.WindowsPhone.Silverlight/Converters/ConvertFolderFlag.cs
 create mode 100644 Noddybox.WindowsPhone.Silverlight/Themes/generic.xaml
 create mode 100644 Noddybox.WindowsPhone.Silverlight/ViewModels/FileDialogViewModel.cs

diff --git a/Noddybox.WindowsPhone.Silverlight/Converters/ConvertFolderFlag.cs b/Noddybox.WindowsPhone.Silverlight/Converters/ConvertFolderFlag.cs
new file mode 100644
index 0000000..433e4f0
--- /dev/null
+++ b/Noddybox.WindowsPhone.Silverlight/Converters/ConvertFolderFlag.cs
@@ -0,0 +1,52 @@
+// This file is part of the Noddybox.WindowsPhone C# suite.
+//
+// Noddybox.Emulation is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Noddybox.Emulation is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Noddybox.Emulation.  If not, see <http://www.gnu.org/licenses/>.
+//
+// Copyright (c) 2012 Ian Cowburn
+//
+using System;
+using System.Net;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Documents;
+using System.Windows.Ink;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Animation;
+using System.Windows.Shapes;
+using System.Windows.Data;
+
+namespace Noddybox.WindowsPhone.Silverlight.Converters
+{
+    /// <summary>
+    /// Convert a boolean flag to an image for a folder or file.
+    /// </summary>
+    public class ConvertFolderFlag : IValueConverter
+    {
+
+        #region IValueConverter Members
+
+        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+        {
+            return (bool)value ? "Resources/folder.png" : "Resources/file.png";
+        }
+
+        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+        {
+            return value.ToString() == "Resources/folder.png";
+        }
+
+        #endregion
+    }
+}
diff --git a/Noddybox.WindowsPhone.Silverlight/Noddybox.WindowsPhone.Silverlight.csproj b/Noddybox.WindowsPhone.Silverlight/Noddybox.WindowsPhone.Silverlight.csproj
index 29b5d6b..1726553 100644
--- a/Noddybox.WindowsPhone.Silverlight/Noddybox.WindowsPhone.Silverlight.csproj
+++ b/Noddybox.WindowsPhone.Silverlight/Noddybox.WindowsPhone.Silverlight.csproj
@@ -51,13 +51,18 @@
     <Reference Include="mscorlib.extensions" />
   </ItemGroup>
   <ItemGroup>
+    <Compile Include="Converters\ConvertFolderFlag.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="SaveDialog.xaml.cs">
       <DependentUpon>SaveDialog.xaml</DependentUpon>
     </Compile>
+    <Resource Include="Themes\generic.xaml">
+      <SubType>Designer</SubType>
+      <Generator>MSBuild:Compile</Generator>
+    </Resource>
     <Compile Include="ViewModels\BaseViewModel.cs" />
     <Compile Include="ViewModels\FileInfo.cs" />
-    <Compile Include="ViewModels\SaveViewModel.cs" />
+    <Compile Include="ViewModels\FileDialogViewModel.cs" />
   </ItemGroup>
   <ItemGroup>
     <Page Include="SaveDialog.xaml">
diff --git a/Noddybox.WindowsPhone.Silverlight/SaveDialog.xaml b/Noddybox.WindowsPhone.Silverlight/SaveDialog.xaml
index 012d2d2..ef45e68 100644
--- a/Noddybox.WindowsPhone.Silverlight/SaveDialog.xaml
+++ b/Noddybox.WindowsPhone.Silverlight/SaveDialog.xaml
@@ -1,16 +1,21 @@
 <UserControl x:Class="Noddybox.WindowsPhone.Silverlight.SaveDialog"
-    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
-    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
-    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
-    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
-    mc:Ignorable="d"
-    FontFamily="{StaticResource PhoneFontFamilyNormal}"
-    FontSize="{StaticResource PhoneFontSizeNormal}"
-    Foreground="{StaticResource PhoneForegroundBrush}"
-    d:DesignHeight="480" d:DesignWidth="480">
-    
-    <Grid x:Name="LayoutRoot">
+             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+             xmlns:conv="clr-namespace:Noddybox.WindowsPhone.Silverlight.Converters"
+             mc:Ignorable="d"
+             FontFamily="{StaticResource PhoneFontFamilyNormal}"
+             FontSize="{StaticResource PhoneFontSizeNormal}"
+             Foreground="{StaticResource PhoneForegroundBrush}"
+             d:DesignHeight="480" d:DesignWidth="480">
+    <UserControl.Resources>
+        <conv:ConvertFolderFlag x:Key="ConvertFolderFlag" />
+    </UserControl.Resources>
+
+    <Grid x:Name="LayoutRoot" >
         <Grid.RowDefinitions>
+            <RowDefinition Height="auto" />
             <RowDefinition Height="*" />
             <RowDefinition Height="auto" />
             <RowDefinition Height="auto" />
@@ -19,9 +24,36 @@
             <ColumnDefinition Width="1*" />
             <ColumnDefinition Width="1*" />
         </Grid.ColumnDefinitions>
-        <ListBox x:Name="fileList" Grid.Row="0" Grid.ColumnSpan="2"/>
-        <TextBox x:Name="fileName" Grid.Row="1" Grid.ColumnSpan="2"/>
-        <Button Grid.Row="2" Grid.Column="0" Content="Ok" />
-        <Button Grid.Row="2" Grid.Column="1" Content="Cancel" />
+        <TextBlock Grid.Row="0" Grid.ColumnSpan="2"
+                   Text="{Binding Path, Mode=OneWay}" Margin="4"/>
+        <ListBox x:Name="fileList" Grid.Row="1" Grid.ColumnSpan="2"
+                 ItemsSource="{Binding FileList, Mode=OneWay}"
+                 SelectionMode="Single"
+                 SelectionChanged="OnFileListSelection">
+            <ListBox.ItemTemplate>
+                <DataTemplate>
+                    <Grid>
+                        <Grid.ColumnDefinitions>
+                            <ColumnDefinition Width="32" />
+                            <ColumnDefinition Width="32" />
+                            <ColumnDefinition Width="*" />
+                        </Grid.ColumnDefinitions>
+                        <Image Grid.Column="0"
+                               Source="{Binding IsFolder, Mode=OneWay, Converter={StaticResource ConvertFolderFlag}}"
+                               VerticalAlignment="Center"
+                               HorizontalAlignment="Center" />
+                        <TextBlock Grid.Column="2"
+                                   Text="{Binding Name, Mode=OneWay}" />
+                    </Grid>
+                </DataTemplate>
+            </ListBox.ItemTemplate>
+        </ListBox>
+        <TextBox x:Name="fileName" Grid.Row="2" Grid.ColumnSpan="2"
+                 KeyUp="OnFilenameKeyUp"/>
+        <Button x:Name="okButton" Grid.Row="3" Grid.Column="0" Content="Ok" 
+                IsEnabled="{Binding IsFileSelected, Mode=OneWay}"
+                Click="OnOKButton"/>
+        <Button x:Name="cancelButton" Grid.Row="3" Grid.Column="1" Content="Cancel" 
+                Click="OnCancelButton"/>
     </Grid>
 </UserControl>
diff --git a/Noddybox.WindowsPhone.Silverlight/SaveDialog.xaml.cs b/Noddybox.WindowsPhone.Silverlight/SaveDialog.xaml.cs
index f807126..8df7b73 100644
--- a/Noddybox.WindowsPhone.Silverlight/SaveDialog.xaml.cs
+++ b/Noddybox.WindowsPhone.Silverlight/SaveDialog.xaml.cs
@@ -26,14 +26,111 @@ using System.Windows.Input;
 using System.Windows.Media;
 using System.Windows.Media.Animation;
 using System.Windows.Shapes;
+using Noddybox.WindowsPhone.Silverlight.ViewModels;
+using System.ComponentModel;
 
 namespace Noddybox.WindowsPhone.Silverlight
 {
+    /// <summary>
+    /// Provides the save dialog user control.
+    /// </summary>
     public partial class SaveDialog : UserControl
     {
+        #region Private data
+
+        private FileDialogViewModel model;
+
+        #endregion
+
+        #region Constructors
+
+        /// <summary>
+        /// Construct a save dialog.
+        /// </summary>
         public SaveDialog()
         {
             InitializeComponent();
+
+            if (!DesignerProperties.IsInDesignTool)
+            {
+                model = new FileDialogViewModel("/");
+                DataContext = model;
+            }
+        }
+
+        #endregion
+
+        #region Properties
+
+        public static readonly DependencyProperty StartPathProperty =
+            DependencyProperty.Register("StartPath", typeof(string), typeof(SaveDialog), null);
+                                        // new PropertyMetadata("StartPath", new PropertyChangedCallback(SaveDialog.OnStartPathChanged)));
+
+        public static readonly DependencyProperty OkButtonTextProperty =
+            DependencyProperty.Register("OkButtonText", typeof(string), typeof(SaveDialog), null);
+                                        // new PropertyMetadata("StartPath", new PropertyChangedCallback(SaveDialog.OnStartPathChanged)));
+
+        private static void OnStartPathChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+        {
+        }
+
+        /// <summary>
+        /// Set the start path
+        /// </summary>
+        public string StartPath
+        {
+            set
+            {
+                if (!DesignerProperties.IsInDesignTool)
+                {
+                    model.Path = value;
+                }
+            }
+        }
+
+        /// <summary>
+        /// Set the contents of the OK button.
+        /// </summary>
+        public string OkButtonText
+        {
+            set
+            {
+            }
         }
+
+        /// <summary>
+        /// Set the contents of the Cancel button.
+        /// </summary>
+        public string CancelButtonText
+        {
+            set {cancelButton.Content = value;}
+        }
+
+        #endregion
+
+        #region Event handlers
+
+        private void OnFilenameKeyUp(object sender, KeyEventArgs e)
+        {
+            model.Filename = fileName.Text;
+        }
+
+        private void OnOKButton(object sender, RoutedEventArgs e)
+        {
+        }
+
+        private void OnCancelButton(object sender, RoutedEventArgs e)
+        {
+        }
+
+        private void OnFileListSelection(object sender, SelectionChangedEventArgs e)
+        {
+            if (e.AddedItems.Count > 0)
+            {
+                model.FileSelected((FileInfo)e.AddedItems[0]);
+            }
+        }
+
+        #endregion
     }
 }
diff --git a/Noddybox.WindowsPhone.Silverlight/Themes/generic.xaml b/Noddybox.WindowsPhone.Silverlight/Themes/generic.xaml
new file mode 100644
index 0000000..74c1d9a
--- /dev/null
+++ b/Noddybox.WindowsPhone.Silverlight/Themes/generic.xaml
@@ -0,0 +1,28 @@
+<!-- This file is part of the Noddybox.WindowsPhone C# suite.
+
+     Noddybox.Emulation is free software: you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published by
+     the Free Software Foundation, either version 3 of the License, or
+     (at your option) any later version.
+
+     Noddybox.Emulation is distributed in the hope that it will be useful,
+     but WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+     GNU General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with Noddybox.Emulation.  If not, see<http://www.gnu.org/licenses/> .
+
+     Copyright (c) 2012 Ian Cowburn
+-->
+<ResourceDictionary
+    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+    xmlns:vsm="clr-namespace:System.Windows;assembly=System.Windows"
+    xmlns:local="clr-namespace:Silverlight">
+    <Style TargetType="local:SaveDialog">
+        <Setter Property="StartPath" Value="/" />
+        <Setter Property="OkButtonText" Value="OK" />
+        <Setter Property="CancelButtonText" Value="Cancel" />
+    </Style>
+</ResourceDictionary>
\ No newline at end of file
diff --git a/Noddybox.WindowsPhone.Silverlight/ViewModels/FileDialogViewModel.cs b/Noddybox.WindowsPhone.Silverlight/ViewModels/FileDialogViewModel.cs
new file mode 100644
index 0000000..afc8e63
--- /dev/null
+++ b/Noddybox.WindowsPhone.Silverlight/ViewModels/FileDialogViewModel.cs
@@ -0,0 +1,159 @@
+// This file is part of the Noddybox.WindowsPhone C# suite.
+//
+// Noddybox.Emulation is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Noddybox.Emulation is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Noddybox.Emulation.  If not, see <http://www.gnu.org/licenses/>.
+//
+// Copyright (c) 2012 Ian Cowburn
+//
+using System;
+using System.Net;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Documents;
+using System.Windows.Ink;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Animation;
+using System.Windows.Shapes;
+using System.Collections.Generic;
+
+namespace Noddybox.WindowsPhone.Silverlight.ViewModels
+{
+    /// <summary>
+    /// Provides a common view model for all file dialogs.
+    /// </summary>
+    public class FileDialogViewModel : BaseViewModel
+    {
+        #region Private data
+
+        private string filename;
+        private string path;
+        private List<FileInfo> fileList;
+
+        #endregion
+        
+        #region Private members
+
+        private void GetFileList()
+        {
+            FileList = FileInfo.GetFiles(path);
+        }
+
+        #endregion
+
+        #region Bindable properties
+
+        /// <summary>
+        /// Get/set the filename.
+        /// </summary>
+        public string Filename
+        {
+            get {return filename;}
+            set {SetValue(ref filename, value, "Filename", "IsFileSelected");}
+        }
+
+        /// <summary>
+        /// Get whether there is a filename.
+        /// </summary>
+        public bool IsFileSelected
+        {
+            get {return !String.IsNullOrWhiteSpace(filename);}
+        }
+
+
+        /// <summary>
+        /// Get the list of files.
+        /// </summary>
+        public List<FileInfo> FileList
+        {
+            get {return fileList;}
+            set {SetValue(ref fileList, value, "FileList"); }
+        }
+
+        /// <summary>
+        /// Get/set the current path.
+        /// </summary>
+        public string Path
+        {
+            get {return path;}
+            set
+            {
+                SetValue(ref path, value, "Path");
+                Filename = String.Empty;
+                GetFileList();
+            }
+        }
+
+        #endregion
+
+        #region Public members
+
+        /// <summary>
+        /// Called when a file is selected.
+        /// </summary>
+        /// <param name="file">The selected file.</param>
+        public void FileSelected(FileInfo file)
+        {
+            if (file.IsFolder)
+            {
+                string newPath = path;
+
+                if (file.Name != "..")
+                {
+                    newPath += file.Name + "/";
+                }
+                else
+                {
+                    if (newPath.Length > 1)
+                    {
+                        string[] parts = newPath.Split(new char[] {'/'}, StringSplitOptions.RemoveEmptyEntries);
+
+                        newPath = "/";
+
+                        for(int f = 0; f < parts.Length-1; f++)
+                        {
+                            newPath += parts[f] + "/";
+                        }
+                    }
+                    else
+                    {
+                        newPath = "/";
+                    }
+                }
+
+                Path = newPath;
+            }
+            else
+            {
+                Filename = file.Name;
+            }
+        }
+
+        #endregion
+
+        #region Constructors
+
+        /// <summary>
+        /// Construct the view model.
+        /// </summary>
+        /// <param name="startPath">The path to start selecting from.</param>
+        public FileDialogViewModel(string startPath)
+        {
+            path = startPath;
+            Filename = String.Empty;
+            GetFileList();
+        }
+
+        #endregion
+    }
+}
diff --git a/Noddybox.WindowsPhone.Test/MainPage.xaml b/Noddybox.WindowsPhone.Test/MainPage.xaml
index f890314..8e80897 100644
--- a/Noddybox.WindowsPhone.Test/MainPage.xaml
+++ b/Noddybox.WindowsPhone.Test/MainPage.xaml
@@ -6,6 +6,7 @@
     xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+    xmlns:noddybox="clr-namespace:Noddybox.WindowsPhone.Silverlight;assembly=Noddybox.WindowsPhone.Silverlight"
     mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768"
     FontFamily="{StaticResource PhoneFontFamilyNormal}"
     FontSize="{StaticResource PhoneFontSizeNormal}"
@@ -27,7 +28,9 @@
         </StackPanel>
 
         <!--ContentPanel - place additional content here-->
-        <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"></Grid>
+        <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
+            <noddybox:SaveDialog />
+        </Grid>
     </Grid>
  
     <!--Sample code showing usage of ApplicationBar-->
-- 
cgit v1.2.3