Imports System.IO
Imports System.Net
Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Documents
Imports System.Windows.Input
Imports System.Windows.Media
Imports System.Windows.Media.Animation
Imports System.Windows.Shapes
Imports C1.Silverlight.FlexGrid
Imports C1.Silverlight

Namespace ColumnPicker
    Partial Public Class MainPage
        Inherits UserControl

        Dim ctxMenu As C1ContextMenu
        Public Sub New()
            InitializeComponent()

            ' populate grid
            _flex.ItemsSource = Product.GetProducts(100)

            ' set clipboard copy/paste mode
            _flex.ClipboardCopyMode = ClipboardCopyMode.ExcludeHeader
            _flex.ClipboardPasteMode = ClipboardCopyMode.ExcludeHeader

            ' set up event handlers for context menu
            AddHandler _flex.MouseRightButtonDown, Function(s, e) AnonymousMethod1(s, e)
            AddHandler _flex.MouseRightButtonUp, Function(s, e) AnonymousMethod2(s, e)

            ' load column layout persisted from previous session, if any
            Dim layoutFileName = "ColumnLayout.xml"
            Dim stg = System.IO.IsolatedStorage.IsolatedStorageFile.GetUserStoreForApplication()
            If stg IsNot Nothing Then
                If stg.FileExists(layoutFileName) Then
                    Using sr = New StreamReader(stg.OpenFile(layoutFileName, FileMode.Open))
                        _flex.ColumnLayout = sr.ReadToEnd()
                    End Using
                End If
            End If

            ' save column layout when application exits
            AddHandler Application.Current.Exit, Function(s, e) AnonymousMethod3(s, e, stg, layoutFileName)

            ' save current layout so user can restore whenever he wants to
            _columnLayout = _flex.ColumnLayout
        End Sub

        Private Function AnonymousMethod1(ByVal s As Object, ByVal e As Object) As Object
            e.Handled = True ' << disable standard "Silverlight" menu
            Return Nothing
        End Function

        Private Function AnonymousMethod2(ByVal s As Object, ByVal e As Object) As Object
            e.Handled = True
            ShowContextMenu(e)
            Return Nothing
        End Function

        Private Function AnonymousMethod3(ByVal s As Object, ByVal e As Object, ByVal stg As System.IO.IsolatedStorage.IsolatedStorageFile, ByVal layoutFileName As String) As Object
            If stg IsNot Nothing Then
                Using sw = New StreamWriter(stg.OpenFile(layoutFileName, FileMode.Create))
                    sw.Write(_flex.ColumnLayout)
                End Using
            End If
            Return Nothing
        End Function

        ' show the context menu
        Private Sub ShowContextMenu(ByVal e As MouseEventArgs)
            ' create context menu
            If (ctxMenu IsNot Nothing) Then
                If (ctxMenu.Visibility = System.Windows.Visibility.Visible) Then
                    ctxMenu.Hide()
                End If
            End If
            ctxMenu = New C1ContextMenu() With {.AutoClose = False}

            ' check what type of cell was clicked to show the right menu
            Dim ht = _flex.HitTest(e)
            Select Case ht.CellType
                ' if the click was on the column headers, show column picker
                Case CellType.ColumnHeader
                    CreateColumnPickerMenu(ctxMenu)

                    ' show clipboard menu if the click was on a regular cell
                Case CellType.Cell

                    ' select cell if not yet selected
                    If Not _flex.Selection.Contains(ht.CellRange) Then
                        _flex.Select(ht.CellRange, False)
                    End If
                    CreateClipboardMenu(ctxMenu)
            End Select

            ' show the menu
            Dim pt = e.GetPosition(LayoutRoot)
            Dim offset = New Point() With {.X = pt.X, .Y = pt.Y}
            ctxMenu.InvalidateMeasure()
            ctxMenu.InvalidateArrange()
            ctxMenu.Show(LayoutRoot, offset)
        End Sub

        ' populate context menu with column picker
        Private Sub CreateColumnPickerMenu(ByVal ctxMenu As C1ContextMenu)
            For Each c In _flex.Columns
                ' create checkbox to represent this column
                Dim chk = New CheckBox()
                chk.Tag = c
                chk.IsChecked = c.Visible
                chk.Content = If((Not String.IsNullOrEmpty(c.Header)), c.Header, c.BoundPropertyName)

                ' create menu item to hold the checkbox
                Dim mi = New C1MenuItem()
                mi.Header = chk
                ctxMenu.Items.Add(mi)

                ' toggle column visibility when checkbox is clicked
                AddHandler chk.Click, Function(s, ea) AnonymousMethod4(s, ea, chk, ctxMenu)
            Next c
        End Sub

        Private Function AnonymousMethod4(ByVal s As Object, ByVal ea As Object, ByVal chk As CheckBox, ByVal ctxMenu As C1ContextMenu) As Object
            Dim col = TryCast(chk.Tag, Column)
            col.Visible = chk.IsChecked.Value
            ctxMenu.Hide()
            Return Nothing
        End Function

        ' populate context menu with clipboard commands
        Private Sub CreateClipboardMenu(ByVal ctxMenu As C1ContextMenu)
            For Each cmd As String In "Cut|Copy|Paste|Delete".Split("|"c)
                ' create menu item to hold the command
                Dim mi = New C1MenuItem()
                mi.Header = cmd
                ctxMenu.Items.Add(mi)

                ' execute commands
                AddHandler mi.Click, Function(s, ea) AnonymousMethod5(s, ea, mi, ctxMenu)
            Next cmd
        End Sub

        Private Function AnonymousMethod5(ByVal s As Object, ByVal ea As Object, ByVal mi As C1MenuItem, ByVal ctxMenu As C1ContextMenu) As Object
            Select Case CStr(mi.Header)
                Case "Cut"
                    _flex.Copy()
                    For Each cell In _flex.Selection.Cells
                        _flex(cell.Row, cell.Column) = Nothing
                    Next cell
                Case "Copy"
                    _flex.Copy()
                Case "Paste"
                    _flex.Paste()
                Case "Delete"
                    For Each cell In _flex.Selection.Cells
                        _flex(cell.Row, cell.Column) = Nothing
                    Next cell
            End Select
            ctxMenu.Hide()
            Return Nothing
        End Function

        ' use the ColumnLayout to save/restore column layout
        ' the ColumnLayout property gets/sets an XML string that contains the 
        ' order, visibility, and width of the columns on the grid.
        Private _columnLayout As String
        Private Sub SaveLayout_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
            _columnLayout = _flex.ColumnLayout
        End Sub
        Private Sub LoadLayout_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
            _flex.ColumnLayout = _columnLayout
        End Sub
    End Class
End Namespace
