Silverlight / WPF - Cell contents focus in XAML forms

Asked By David on 06-Jul-11 02:55 AM

 Hi All
 I have just had a problem solved of moving around a data input form using Tab or Eneter keys which was perfect
 I now need the cell moving into to have focus on its the entire field so I can just enter a new figure to replace the current one.
 At the moment the cursor is flashing at the left side off any data in the cell so you have to delete it before  entering   new Data 

 This is on XAML forms

 Thanks David
pete rainbow replied to David on 06-Jul-11 10:44 AM
bit of a tricky one this...

if just using the keyboard then you could just handle the GotFocus event on each text box

and the handler do something like the following
private void TextBox_GotFocus(object sender, RoutedEventArgs e)
   
{
       
(sender as TextBox).SelectAll();
   
}
however if they use the mouse button to move focus it gets tricky...
pete rainbow replied to David on 06-Jul-11 10:45 AM
btw with this extra behaviour i'd be starting to be thinking about creating a control derived from the textbox which has the behaviours ( eg enter doing a tab ) and auto select

then using that to add to the form
pete rainbow replied to David on 06-Jul-11 01:05 PM
bored again...so i knocked up this dependency property class that allows you to attach to an existing form and set both the enter as tab properties and auto select on tab entry

for example if your text box in a grid

ref to namespace       xmlns:my="clr-namespace:WpfApplication1DelMe"

then     <Grid my:SmartText.AutoSelect="True" my:SmartText.EnterAsTab="True" Name="Grid1">

the autoselect can also be done at the textbox only level too

only lightly tested, but might be of interest to you anyway as demonstrates sly use of dependency props...

================= Create a new Class containing this code ===========

Public Class SmartText

#Region "EnterAsTab"


    Public Shared Function GetEnterAsTab(ByVal obj As DependencyObject) As Boolean

      GetEnterAsTab = obj.GetValue(EnterAsTabProperty)

    End Function

    Public Shared Sub SetEnterAsTab(ByVal obj As DependencyObject, ByVal value As Boolean)

      obj.SetValue(EnterAsTabProperty, value)

    End Sub

    Public Shared Sub ue_PreviewKeyDown(ByVal sender As Object, ByVal e As System.Windows.Input.KeyEventArgs)
      Dim ue As FrameworkElement

      ue = e.OriginalSource
      If (e.Key = Key.Enter) Then
        e.Handled = True
        ue.MoveFocus(New TraversalRequest(FocusNavigationDirection.Next))
      End If
    End Sub


    Private Shared Sub ue_Unloaded(ByVal sender As Object, ByVal e As RoutedEventArgs)
      Dim ue As FrameworkElement

      ue = sender

      If (ue Is Nothing) Then Return

      RemoveHandler ue.Unloaded, AddressOf ue_Unloaded
      RemoveHandler ue.PreviewKeyDown, AddressOf ue_PreviewKeyDown
    End Sub


    Public Shared ReadOnly EnterAsTabProperty As DependencyProperty = DependencyProperty.RegisterAttached("EnterAsTab", GetType(Boolean), GetType(SmartText), New UIPropertyMetadata(False, AddressOf EnterAsTabChanged))

    Public Shared Sub EnterAsTabChanged(ByVal d As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs)
      Dim ue As FrameworkElement
      ue = d
      If (ue Is Nothing) Then Return

      If (e.NewValue) Then
        AddHandler ue.Unloaded, AddressOf ue_Unloaded
        AddHandler ue.PreviewKeyDown, AddressOf ue_PreviewKeyDown
      Else
        RemoveHandler ue.PreviewKeyDown, AddressOf ue_PreviewKeyDown
      End If
    End Sub

#End Region


#Region "AutoSelect"


    Public Shared Function GetAutoSelect(ByVal obj As DependencyObject) As Boolean

      GetAutoSelect = obj.GetValue(AutoSelectProperty)

    End Function

    Public Shared Sub SetAutoSelect(ByVal obj As DependencyObject, ByVal value As Boolean)

      obj.SetValue(AutoSelectProperty, value)

    End Sub

    Public Shared Sub ue_GotFocus(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
      Dim ue As TextBox = sender

      ue.SelectAll()

    End Sub

    Private Shared Sub ue_AutoSelectContainerLoaded(ByVal sender As Object, ByVal e As RoutedEventArgs)

      Dim pa As FrameworkElement = sender
      RemoveHandler pa.Loaded, AddressOf ue_AutoSelectContainerLoaded

      For i = 1 To VisualTreeHelper.GetChildrenCount(sender)

        Dim dobj As DependencyObject = VisualTreeHelper.GetChild(sender, i - 1)

        If TypeOf dobj Is TextBox Then
          Dim txt As TextBox = dobj
          AddHandler txt.Unloaded, AddressOf ue_AutoSelectUnloaded
          AddHandler txt.GotFocus, AddressOf ue_GotFocus
        End If

      Next

    End Sub

    Private Shared Sub ue_AutoSelectUnloaded(ByVal sender As Object, ByVal e As RoutedEventArgs)
      Dim ue As TextBox

      ue = sender

      If (ue Is Nothing) Then Return

      RemoveHandler ue.Unloaded, AddressOf ue_AutoSelectUnloaded
      RemoveHandler ue.GotFocus, AddressOf ue_GotFocus
    End Sub


    Public Shared ReadOnly AutoSelectProperty As DependencyProperty = DependencyProperty.RegisterAttached("AutoSelect", GetType(Boolean), GetType(SmartText), New UIPropertyMetadata(False, AddressOf AutoSelectChanged))

    Public Shared Sub AutoSelectChanged(ByVal d As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs)

      If Not TypeOf d Is TextBox Then

        If Not TypeOf d Is FrameworkElement Then Return

        Dim pa As FrameworkElement = d

        If (e.NewValue) Then
          AddHandler pa.Loaded, AddressOf ue_AutoSelectContainerLoaded
        Else
          RemoveHandler pa.Loaded, AddressOf ue_AutoSelectContainerLoaded
          For i = 0 To VisualTreeHelper.GetChildrenCount(pa)

            Dim dobj As DependencyObject
            dobj = VisualTreeHelper.GetChild(pa, i)

            If TypeOf dobj Is TextBox Then
              Dim txt As TextBox = dobj
              RemoveHandler txt.GotFocus, AddressOf ue_GotFocus
            End If

          Next
        End If

        Return

      Else

        Dim ue As TextBox = d

        If (e.NewValue) Then
          AddHandler ue.Unloaded, AddressOf ue_AutoSelectUnloaded
          AddHandler ue.GotFocus, AddressOf ue_GotFocus
        Else
          RemoveHandler ue.GotFocus, AddressOf ue_GotFocus
        End If
      End If

    End Sub

#End Region

    Private Shared Sub DumpLogicalTree(ByVal parent As Object, ByVal level As Integer)

      Dim doParent As DependencyObject
      Dim typeName As String = parent.GetType().Name
      Dim name As String = Nothing

      If (TypeOf parent Is DependencyObject) Then
        doParent = parent
        name = doParent.GetValue(FrameworkElement.NameProperty)
        Trace.WriteLine(String.Format("{0}: {1}", typeName, name))

        For Each child In LogicalTreeHelper.GetChildren(doParent)
          DumpLogicalTree(child, level + 1)
        Next
      Else
        name = parent.ToString()
        Trace.WriteLine(String.Format("{0}: {1}", typeName, name))
        Return

      End If



    End Sub

End Class
David replied to pete rainbow on 06-Jul-11 04:05 PM

 Hi Pete
 Thanks again for your reply 
 I have copied the code from   Public Class SmartText down to end sub
 and below is the error I get 
 The i is underlined with a squiggle
 Have I copied too much 

For i = 0 To VisualTreeHelper.GetChildrenCount(pa)

Error 1 Constant cannot be the target of an assignment. 
This error shows on the i in 2 places and will not allow programme to run
 I was ok using Access but this has me beat
 
 Thanks again
 David

pete rainbow replied to David on 06-Jul-11 04:23 PM
steps you need to do are...

add a new class module ( usually shortcut of shift-alt-C )

then in the name bit type in SmartText.vb

then a new 'file' will have been added to which you can open and paste in the text

that should do the job
David replied to pete rainbow on 06-Jul-11 04:41 PM
  Hi Pete
  I have made a new Module called SmartText.vb and pasted all your code in
 The programme runs o/k but in the form focus is not on the contents of the cell still focus on the left side
 but the Tab and Enter keys work ok
 Thanks

 David
pete rainbow replied to David on 06-Jul-11 04:46 PM
did you add the attribute to the text box or grid?

you might want to add a breakpoint to the property changed method for the autoselect and see what happens there

if that works ok then add breakpoint to the got focus method and check thats working
David replied to pete rainbow on 06-Jul-11 04:52 PM
 Hi Pete

 I am not sure what I am doing but I pasted all your code into the module and nothing into the XAML form or its code  page
 
 Thanks for all your help

 David
pete rainbow replied to David on 06-Jul-11 06:31 PM
ok thats a start

once you've built the app ctrl-alt-b

so remove what you've done in the mainform vb

then go to the designer of the main form

and add the following,you'll see some similar xmls bits in the xaml, just past this into next to them
and replace XXXXXX with whatever your project is called

xmlns:my="clr-namespace:XXXXXXXXX"

finally add the 2 properties to your top level grid or panel or whatever it is

<Grid my:SmartText.AutoSelect="True" my:SmartText.EnterAsTab="True" Name="Grid1">
David replied to David on 07-Jul-11 05:46 AM
  Hi Pete
 Thanks for all the trouble I have put you through
 I have the following in my XAML
 

<Window x:Class="Window3"

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

xmlns:local="clr-namespace:WpfDataEntry"

xmlns:my="clr-namespace:Golf ver6 DA"
 The namespace  has an under line and does not like it but with the forms running ok with Tab or Enter keys so I will have to leave it without whole field selected .
I wish you lived closer and maybe you could solve my main problem of passing a query code to run on Datagrid view.
I have posted this before but never solved it

Thanks David from Burton On Trent