Imports System.Windows
Imports System.Windows.Controls

Namespace Extensions

    Public Class ListViewAttached
        Inherits DependencyObject

        Public Shared ReadOnly StretchProperty As DependencyProperty =
        DependencyProperty.RegisterAttached("Stretch",
        GetType(Boolean),
        GetType(ListViewAttached),
        New UIPropertyMetadata(True, Nothing, AddressOf OnCoerceStretch))

        Public Shared Function GetStretch(obj As DependencyObject) As Boolean
            Return CBool(obj.GetValue(StretchProperty))
        End Function

        Public Shared Sub SetStretch(obj As DependencyObject, value As Boolean)
            obj.SetValue(StretchProperty, value)
        End Sub

        Private Shared Function OnCoerceStretch(d As DependencyObject, baseValue As Object) As Object
            Dim lv As ListView = TryCast(d, ListView)

            If lv Is Nothing Then
                Throw New ArgumentException("This property may only be used on ListViews")
            End If

            lv.AddHandler(ListView.LoadedEvent, New RoutedEventHandler(AddressOf lv_loaded))
            lv.AddHandler(ListView.SizeChangedEvent, New RoutedEventHandler(AddressOf lv_SizeChanged))

            Return baseValue
        End Function
  
        Private Shared Sub lv_SizeChanged(sender As Object, e As RoutedEventArgs)
            Dim lv = TryCast(sender, ListView)
            If lv.IsLoaded Then
                SetColumnWidths(lv)
            End If
        End Sub

        Private Shared Sub lv_loaded(sender As Object, e As RoutedEventArgs)
            Dim lv = TryCast(sender, ListView)
            SetColumnWidths(lv)
        End Sub

        Private Shared Sub SetColumnWidths(lv As ListView)
            Dim columns As List(Of GridViewColumn) = TryCast(lv.Tag, List(Of GridViewColumn))
            Dim specifiedWidth As Double = 0
            Dim gridView As GridView = lv.View
            If Not gridView Is Nothing Then
                If columns Is Nothing Then
                    columns = New List(Of GridViewColumn)()

                    For Each column As GridViewColumn In gridView.Columns
                        If Not column.Width >= 0 Then
                            columns.Add(column)
                        Else
                            specifiedWidth += column.ActualWidth
                        End If
                    Next
                Else
                    For Each column As GridViewColumn In gridView.Columns
                        If Not columns.Contains(column) Then
                            specifiedWidth += column.ActualWidth
                        End If
                    Next
                End If

                For Each column As GridViewColumn In columns
                    Dim newWidth As Double = (lv.ActualWidth - specifiedWidth) / columns.Count
                    If newWidth >= 0 Then
                        column.Width = newWidth - 30
                    End If
                Next

                lv.Tag = columns
            End If
        End Sub

    End Class

End Namespace
