This is a migrated thread and some comments may be shown as answers.

Using on screen keyboard

8 Answers 763 Views
AutoCompleteBox
This is a migrated thread and some comments may be shown as answers.
Damien
Top achievements
Rank 1
Damien asked on 28 Mar 2018, 09:01 PM

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)

 

8 Answers, 1 is accepted

Sort by
0
Vladimir Stoyanov
Telerik team
answered on 02 Apr 2018, 11:40 AM
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.
0
Damien
Top achievements
Rank 1
answered on 02 Apr 2018, 02:15 PM

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
}
0
Vladimir Stoyanov
Telerik team
answered on 05 Apr 2018, 12:23 PM
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.
0
Damien
Top achievements
Rank 1
answered on 05 Apr 2018, 05:23 PM
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.  
0
Vladimir Stoyanov
Telerik team
answered on 10 Apr 2018, 01:39 PM
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.
0
Damien
Top achievements
Rank 1
answered on 11 Apr 2018, 09:01 PM

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.

0
Software
Top achievements
Rank 1
answered on 11 Jul 2018, 03:40 PM

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

0
Software
Top achievements
Rank 1
answered on 13 Jul 2018, 03:30 PM

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

Regards,

MReddy

Tags
AutoCompleteBox
Asked by
Damien
Top achievements
Rank 1
Answers by
Vladimir Stoyanov
Telerik team
Damien
Top achievements
Rank 1
Software
Top achievements
Rank 1
Share this question
or