Using on screen keyboard

9 posts, 0 answers
  1. Damien
    Damien avatar
    4 posts
    Member since:
    Mar 2018

    Posted 28 Mar Link to this post

    When using an onscreen keyboard with the autocomplete box, when the dropdown is open you need to click twice on the keyboard to press a key. Once to close the dropdown and once to press the key. 

    I have figured out that the MouseLeave event is fired when the dropdown is open and you click outside of it or when closed and leave the watermarktextbox. So, I am able to resend the mouse event to avoid clicking twice, but the drop down still closes. This is ok when the search text changes as it will reopen with the new values. However, when the up/down arrow keys are pressed it closes and doesn't reopen with no way to know what is highlighted in the list. 

    Is there an event or method that could be overridden to keep the dropdown open if focus doesn't change? (The on screen keyboard doesn't take focus)

     

  2. Vladimir Stoyanov
    Admin
    Vladimir Stoyanov avatar
    253 posts

    Posted 02 Apr Link to this post

    Hello Damien,

    May I ask you some questions in order to better assist you? Can you specify when and how you are opening the onscreen keyboard? Additionally, may I ask you to explain what you meant by "resend the mouse event to avoid clicking twice"? If you are able to share some code samples as to how you are opening the onscreen keyboard and handling the MouseLeave event I will be able to better understand your scenario. Also, providing a video of how the process looks on your side or any other details you find relevant would be of help as well. 

    I am looking forward to your reply.

    Regards,
    Vladimir Stoyanov
    Progress Telerik
    Want to extend the target reach of your WPF applications, leveraging iOS, Android, and UWP? Try UI for Xamarin, a suite of polished and feature-rich components for the Xamarin framework, which allow you to write beautiful native mobile apps using a single shared C# codebase.
  3. Damien
    Damien avatar
    4 posts
    Member since:
    Mar 2018

    Posted 02 Apr in reply to Vladimir Stoyanov Link to this post

    We are using a custom on screen keyboard from mindfusion.eu.  I am unable to attach video wav files here, is there somewhere I could uploaded or send them.

    What I am really interested in is having the dropdown stay open when clicking on the keyboard.   Adding IsDropDownOpen = true to the OnMouseLeave doesn't do it. 

    We are using asynchronous filtering and here the drop down xaml. 

    <telerik:RadAutoCompleteBox x:Name="EmailBox"
                                Grid.Row="1"
                                IsTabStop="True"
                                VerticalAlignment="Center"
                                WatermarkContent="Enter email address"
                                MinWidth="350"
                                FontSize="18"
                                SelectedItems="{Binding Path=AdditionalParticipantEmails, Mode=TwoWay}"
                                Margin="0,10,10,10"
                                SelectionMode="Multiple"
                                TextSearchMode="Contains"
                                AutoCompleteMode="Suggest"
                                FilteringBehavior="{StaticResource EmailFilteringBehavior}">
        <i:Interaction.Behaviors>
            <behaviors:EmailRadAutoCompleteBoxBehavior />
        </i:Interaction.Behaviors>
    </telerik:RadAutoCompleteBox>

     

    the code for the filtering

     
    public class EmailFilteringBehavior : IFilteringBehavior, IAsyncItemSearch, IDisposable
        {
            #region Fields
     
            private CancellationTokenSource _CurrentCancellationTokenSource;
            private string _CurrentSearchText;
            private AccountSettingsViewModel _Account;
     
            #endregion
     
            #region IAsyncItemSearch Members
     
            public void FindItems(Predicate<object> match)
            {
                //Here we ignore the match variable since we don't need this
                if (_CurrentCancellationTokenSource == null)
                {
                    _CurrentCancellationTokenSource = new CancellationTokenSource();
                }
                else
                {
                    _CurrentCancellationTokenSource.Cancel(true);
                }
                _CurrentCancellationTokenSource = new CancellationTokenSource();
                CancellationToken cancellationToken = _CurrentCancellationTokenSource.Token;
                Task.Factory.StartNew(() => GetEmailAddressesFromExchange(_CurrentSearchText, _Account, cancellationToken), cancellationToken, TaskCreationOptions.LongRunning, TaskSchedulerPriority.Normal)
                    .ContinueWith(task => ProcessFilteredItems(task.Result), cancellationToken, TaskContinuationOptions.AttachedToParent, TaskScheduler.FromCurrentSynchronizationContext());
            }
     
            public object GetValue(object item)
            {
                throw new NotImplementedException();
            }
     
            public event EventHandler<AsyncItemSearchEventArgs> ItemsFound;
     
            #endregion
     
            #region IDisposable Members
     
            public void Dispose()
            {
                if (_CurrentCancellationTokenSource == null)
                {
                    return;
                }
                _CurrentCancellationTokenSource.Dispose();
            }
     
            #endregion
     
            #region IFilteringBehavior Members
     
            public IEnumerable<object> FindMatchingItems(string searchText, IList items, IEnumerable<object> escapedItems, string textSearchPath, TextSearchMode textSearchMode)
            {
                _CurrentSearchText = searchText;
                _Account = MainViewModel.Instance.SecurityManager.CurrentUser;
                if (MainViewModel.Instance.NewSettings.Calendar.EmailAutoComplete)
                {
                    FindItems(itemText => true);
                }
                return Enumerable.Empty<object>();
            }
     
            #endregion
     
            #region Non-Public Methods
     
            protected List<string> GetEmailAddressesFromExchange(string searchText, AccountSettingsViewModel account, CancellationToken cancellationToken)
            {
                var searchItems = new List<string>();
                if (cancellationToken.IsCancellationRequested)
                {
                    return searchItems;
                }
                if (string.IsNullOrWhiteSpace(searchText))
                {
                    return searchItems;
                }
                try
                {
                    if (MainViewModel.Instance.ProductManager.CurrentEdition.Features.CalendarProviders.IsAvailable)
                    {
                        using (IEmailProviderAdapter emailProvider = MainViewModel.Instance.ProductManager.CreateEmailProviderAdapter(account))
                        {
                            IReadOnlyList<Address> resolvedNames = emailProvider.ResolveName(searchText);
                            searchItems.AddRange(resolvedNames.Select(p => p.Email));
                        }
                    }
                }
                catch (Exception ex)
                {
                    ex.LogErrorDeep();
                }
                return searchItems;
            }
     
            private void ProcessFilteredItems(List<string> items)
            {
                if (ItemsFound != null)
                {
                    ItemsFound((object) null, new AsyncItemSearchEventArgs(items));
                }
            }
     
            #endregion
        }

     

    And the code for the AutoCompleteBehaviour

    public class EmailRadAutoCompleteBoxBehavior : DelayRadAutoCompleteBoxBehavior
    {
        #region Non-Public Methods
     
        protected override void OnAttached()
        {
            var autoComplete = AssociatedObject as RadAutoCompleteBox;
            if (autoComplete != null)
            {
                autoComplete.KeyDown += OnAutoCompleteBoxKeyDown;
                autoComplete.LostFocus += OnAutoCompleteBoxLostFocus;
                autoComplete.SelectionChanged += OnSelectionChanged;
                autoComplete.IsVisibleChanged += OnIsVisibleChanged;
                autoComplete.MouseLeave += AutoCompleteOnMouseLeave;
            }
        }
     
        private void AutoCompleteOnMouseLeave(object sender, MouseEventArgs mouseEventArgs)
        {
            var autoComplete = sender as RadAutoCompleteBox;
            if (autoComplete.IsDropDownOpen)
            {
                Point m = Mouse.GetPosition(autoComplete);
                Point p = autoComplete.PointToScreen(m);
                 
                User32.LeftMouseClick(Convert.ToInt32(p.X), Convert.ToInt32(p.Y));
            }
        }
     
     
        private void OnAutoCompleteBoxKeyDown(object sender, KeyEventArgs e)
        {
            var autoComplete = AssociatedObject as RadAutoCompleteBox;
            if (e.Key == Key.OemSemicolon)
            {
                if (RegexExtensions.IsValidEmail(autoComplete.SearchText) && autoComplete.DataContext != null)
                {
                    var selectedItems = new ObservableCollection<string>(autoComplete.SelectedItems.Cast<string>())
                    {
                        autoComplete.SearchText
                    };
                    autoComplete.SelectedItems = selectedItems;
                    autoComplete.SearchText = string.Empty;
                }
                e.Handled = true;
                //Debug.WriteLine(string.Format("EmailRadAutoCompleteBoxBehavior.OnAutoCompleteBoxKeyDown e.Key: {0}  SearchText:{1}", e.Key, autoComplete.SearchText));
            }
        }
     
        private void OnAutoCompleteBoxLostFocus(object sender, RoutedEventArgs e)
        {
            var autoComplete = AssociatedObject as RadAutoCompleteBox;
            if (RegexExtensions.IsValidEmail(autoComplete.SearchText) && autoComplete.DataContext != null)
            {
                var selectedItems = new ObservableCollection<string>(autoComplete.SelectedItems.Cast<string>())
                {
                    autoComplete.SearchText
                };
                autoComplete.SelectedItems = selectedItems;
                autoComplete.SearchText = string.Empty;
                //Debug.WriteLine(string.Format("EmailRadAutoCompleteBoxBehavior.OnAutoCompleteBoxLostFocus SearchText:{0}", autoComplete.SearchText));
            }
        }
     
        protected override void OnDetaching()
        {
            var autoComplete = AssociatedObject as RadAutoCompleteBox;
            if (autoComplete != null)
            {
                autoComplete.KeyDown -= OnAutoCompleteBoxKeyDown;
                autoComplete.LostFocus -= OnAutoCompleteBoxLostFocus;
                autoComplete.IsVisibleChanged -= OnIsVisibleChanged;
                autoComplete.MouseLeave -= AutoCompleteOnMouseLeave;
            }
        }
     
        private void OnIsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            var autoComplete = AssociatedObject as RadAutoCompleteBox;
            if (autoComplete.Visibility == Visibility.Visible)
            {
                autoComplete.SearchText = string.Empty;
                //Debug.WriteLine(string.Format("EmailRadAutoCompleteBoxBehavior.OnIsVisibleChanged SearchText:{0}", autoComplete.SearchText));
            }
        }
     
        private void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            var autoComplete = AssociatedObject as RadAutoCompleteBox;
            var selectedItems = new ObservableCollection<string>(autoComplete.SelectedItems.Cast<string>());
            autoComplete.SelectedItems = selectedItems;
            autoComplete.SearchText = string.Empty;
        }
     
        #endregion
    }
  4. Vladimir Stoyanov
    Admin
    Vladimir Stoyanov avatar
    253 posts

    Posted 05 Apr Link to this post

    Hello Damien,

    Thank you for the provided code snippets.

    I am afraid I am still unable to reproduce the described scenario on my side. I am attaching a sample project which shows the windows onscreen keyboard in the GotFocus event of the RadAutoCompleteBox. I was able to type in the RadAutoCompleteBox from the onscreen keyboard with a single click. Can you share what you are doing differently on your side? This way I will be able to investigate further.

    Regards,
    Vladimir Stoyanov
    Progress Telerik
    Want to extend the target reach of your WPF applications, leveraging iOS, Android, and UWP? Try UI for Xamarin, a suite of polished and feature-rich components for the Xamarin framework, which allow you to write beautiful native mobile apps using a single shared C# codebase.
  5. Damien
    Damien avatar
    4 posts
    Member since:
    Mar 2018

    Posted 05 Apr in reply to Vladimir Stoyanov Link to this post

    Hi Vladimir, the problem I am looking to solve is the drop down closes when pressing keys, specifically the up/down arrows, so you are unable to see which item in the list is highlighted.  
  6. Vladimir Stoyanov
    Admin
    Vladimir Stoyanov avatar
    253 posts

    Posted 10 Apr Link to this post

    Hello Damien,

    By default the RadAutoCompleteBox's drop down is closed when the mouse is captured away from the RadWatermarkTextBox which is inside it. This happens when the up/down keys of the on screen keyboard are pressed.

    The only suggestion I can offer in order to prevent this is to handle the PreviewMouseDownEvent event of the RadAutocompleteBox. Then you can set the e.Handled="true" if the up/down button of the virtual keyboard was pressed and the dropdown is open. Please note that this would require knowing that the virtual keyboard's up/down keys were pressed in the PreviewMouseDownEvent.

    Regards,
    Vladimir Stoyanov
    Progress Telerik
    Want to extend the target reach of your WPF applications, leveraging iOS, Android, and UWP? Try UI for Xamarin, a suite of polished and feature-rich components for the Xamarin framework, which allow you to write beautiful native mobile apps using a single shared C# codebase.
  7. Damien
    Damien avatar
    4 posts
    Member since:
    Mar 2018

    Posted 11 Apr in reply to Vladimir Stoyanov Link to this post

    Vladimir,  I am able to process successfully with PreviewMouseDownEvent and PreviewTouchDownEvent. I was able to check if the event occurs over our custom on screen keyboard, press the correct key and mark the event as handled. 

    Thanks for all the help.

  8. Software
    Software avatar
    2 posts
    Member since:
    Jul 2018

    Posted 11 Jul in reply to Damien Link to this post

    Hi Damien,

    Good to hear that you were able to resolve the issue.

    I am facing same issue with mind fusion key board with rad auto complete. Can u please elaborate how did u solve this issue.

    Thanks in advance

     

    Regards,

    MReddy

  9. Software
    Software avatar
    2 posts
    Member since:
    Jul 2018

    Posted 13 Jul in reply to Software Link to this post

    Thanks to Vladimir  & Damien, your inputs helped me to resolve the issue.

    Regards,

    MReddy

Back to Top