Make Keyboard popup automatically on entry - xamarin.forms

I am using a grid in Xamain forms and I want on the selection event to call the keyboard I thought doing this word wok.
I am using the plugin dialogue kit to display a numeric entry but my quesiton is the keyboard is only displaying on the text box when it has focus how Do I force the keyboard to come up so the user does not have to click into the field.
new Entry()
{
Keyboard = Keyboard.Numeric
};
var resultQty = await Plugin.DialogKit.CrossDiaglogKit.Current.GetInputTextAsync("Test", $"Please goto Bin {item.BinName} , and enter the visible stock of the item." + item.Name, null, Keyboard.Numeric);
The code from Dialog kit shows that it attempts to place a focus on the entry field.
<ContentView.Content>
<StackLayout Padding="10" BackgroundColor="White" VerticalOptions="CenterAndExpand" Margin="25">
<Label FontAttributes="Bold" FontSize="Large" Text="{Binding Title}"/>
<Label FontSize="Large" Text="{Binding Message}"/>
<Entry x:Name="txtInput" Keyboard="{Binding Keyboard}"/>
<StackLayout Margin="10" Orientation="Horizontal">
<Button Text="{Binding OK}" Clicked="Confirm_Clicked" HorizontalOptions="FillAndExpand"/>
<Button Text="{Binding Cancel}" Clicked="Cancel_Clicked" HorizontalOptions="FillAndExpand"/>
</StackLayout>
</StackLayout>
</ContentView.Content>
You will see here that the dialog kit calls the above few as such
public Task<string> GetInputTextAsync(string title, string message,string currentText = null, Keyboard keyboard = null)
{
if (keyboard == null) keyboard = Keyboard.Default;
var cts = new TaskCompletionSource<string>();
var _dialogView = new Plugin.DialogKit.Views.InputView(title, message,currentText,keyboard);
_dialogView.FocusEntry();
_dialogView.Picked += (s, o) => { cts.SetResult(o); PopupNavigation.PopAsync(); };
PopupNavigation.PushAsync(new PopupPage { Content = _dialogView });
return cts.Task;
}
Which as you can see is calling the but i think the placement of this is wrong as its before its pops onto the view.
public void FocusEntry()
{
txtInput.Focus();
}
​

I did some test and found you should Call the FocusEntry after PopUp to force the keyboard to come up automatically.
private async void Button_Clicked(object sender, EventArgs e)
{
var resultQty = await GetInputTextAsync("Test", $"Please goto Bin, the visible stock of the item.", null, Keyboard.Numeric);
}
public async Task<string> GetInputTextAsync(string title, string message, string currentText = null, Keyboard keyboard = null)
{
if (keyboard == null) keyboard = Keyboard.Default;
var cts = new TaskCompletionSource<string>();
var _dialogView = new Plugin.DialogKit.Views.InputView(title, message, currentText, keyboard);
_dialogView.Picked += (s, o) => { cts.SetResult(o); PopupNavigation.PopAsync(); };
await PopupNavigation.PushAsync(new PopupPage { Content = _dialogView });
//Call the FocusEntry after PopUp
_dialogView.FocusEntry();
return await cts.Task;
}

Related

column row is not getting selected/highlighted on window when user presses any letter key on Keyboard

My problem is column row is not getting selected/highlighted on window when user presses any letter key on Keyboard.
I tried following code but when I use DataGridTextSearchBehaviour then SelectionChanged="DataGrid_SelectionChanged" is not working.
<DataGrid ItemsSource="{Binding DrugItems}" SelectedItem="{Binding SelectedDrugItem}"
SelectionChanged="DataGrid_SelectionChanged" Grid.Row="1" Grid.RowSpan="2" Grid.Column="0"
Grid.ColumnSpan="2" HorizontalScrollBarVisibility="Visible">
<i:Interaction.Behaviors>
<b:DataGridTextSearchBehavior />
</i:Interaction.Behaviors>
<DataGrid.Columns>
<DataGridTextColumn Header="{DynamicResource lang.ui.DrugName}" Binding="{Binding Brand_Name}" Width="Auto"
ElementStyle="{StaticResource verticalCenter}">
</DataGridTextColumn>
<DataGridTextColumn Header="{DynamicResource lang.ui.DoseForm}" Binding="{Binding Dose_Form}"
ElementStyle="{StaticResource verticalCenter}"/>
<DataGridTextColumn Header="{DynamicResource lang.ui.UOM}" Binding="{Binding UOM}"
ElementStyle="{StaticResource verticalCenter}"/>
</DataGrid.Columns>
</DataGrid>
I have created DataGridTextSearchBehavior this seperate class ,and if I set AssociatedObject.SelectionUnit = DataGridSelectionUnit.FullRow; then problem gets resolved but instead of selecting column full row gets selected which I dont need. I need to select/Highlight column wise data.
using System;
using System.Linq;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Interactivity;
namespace eIVFRes.Behaviors
{
public class DataGridTextSearchBehavior : Behavior<DataGrid>
{
private DataGridSelectionUnit _oldUnit;
public string TextPath
{
get => TextSearch.GetTextPath(AssociatedObject);
set => TextSearch.SetTextPath(AssociatedObject, value ?? string.Empty);
}
protected override void OnAttached()
{
// <Setter Property="IsTextSearchEnabled" Value="True" />
//<Setter Property="IsTextSearchCaseSensitive" Value="False" />
base.OnAttached();
AssociatedObject.IsTextSearchEnabled = true;
AssociatedObject.IsTextSearchCaseSensitive = false;
_oldUnit = AssociatedObject.SelectionUnit;
AssociatedObject.SelectionUnit = DataGridSelectionUnit.Cell;
AssociatedObject.SelectedCellsChanged += DataGrid_OnSelectedCellsChanged;
}
protected override void OnDetaching()
{
AssociatedObject.IsTextSearchEnabled = false;
AssociatedObject.SelectionUnit = _oldUnit;
AssociatedObject.SelectedCellsChanged -= DataGrid_OnSelectedCellsChanged;
base.OnDetaching();
}
private void DataGrid_OnSelectedCellsChanged(object sender, SelectedCellsChangedEventArgs e)
{column row is not getting selected/highlighted on window when user presses any letter key on Keyboard.
if (!ReferenceEquals(sender, AssociatedObject))
return;
if (!AssociatedObject.SelectedCells.Any())
return;
var c = AssociatedObject.SelectedCells.First();
if (!(c.Column is DataGridTextColumn ct))
return;
var path = (ct.Binding as Binding)?.Path.Path ?? string.Empty;
if (string.IsNullOrWhiteSpace(path))
{
if (!string.IsNullOrWhiteSpace(TextPath))
{
TextPath = string.Empty;
TextSearch.SetText(AssociatedObject, string.Empty);
}
}
else
{
if (!path.Equals(TextPath, StringComparison.CurrentCulture))
{
TextPath = path;
TextSearch.SetText(AssociatedObject, string.Empty);
}
}
}
}
}

Fixed point button using absolute layout not responding to events

I have a listview on a content page. I have placed a fixed point button(think that is proper name) on the page using AvsoluteLayout. I have the button going to the top of the view using RaiseChild. The click event is not firing on the button but on the list view.
my on appearing where bubblebutton is the item at issue
protected override void OnAppearing()
{
base.OnAppearing();
IsBusy = true;
if(viewModel.PlayerActivities == null)
{
viewModel.LoadPlayerActivites.Execute(null);
}
IsBusy = false;
grid.RaiseChild(bubblebutton);
bubblebutton.Clicked += Bubblebutton_Clicked;
}
```
```
<AbsoluteLayout >
<ImageButton x:Name="bubblebutton"
BackgroundColor="Transparent"
Source="st_fab_button.png"
AbsoluteLayout.LayoutBounds="3,500,700,80"
Clicked="bubblebutton_Clicked"
IsEnabled="True"
/>
</AbsoluteLayout>
```
[button click is not happening][1]
Thank you for any help sorry for poor clip art skill
[1]: https://i.stack.imgur.com/QJixO.png
Welcome to SO !
If using Button inside Item of ListView , should use the MVVM architecture to do . That means we should use Binding model to get the click event .
Such as modified code as follow :
```
<AbsoluteLayout >
<ImageButton x:Name="bubblebutton"
BackgroundColor="Transparent"
Source="st_fab_button.png"
AbsoluteLayout.LayoutBounds="3,500,700,80"
Command="{Binding MyCommand}"
IsEnabled="True"
/>
</AbsoluteLayout>
```
Then in your ViewModle should declare the MyCommand :
public ICommand MyCommand { private set; get; }
public ViewModel()
{
MyCommand = new Command(
execute: () =>
{
// do some thing
RefreshCanExecutes();
},
canExecute: () =>
{
// return !IsEditing;
});
···
}
In addition , you also can pass Parameters , more info can have a look at this document .

Set Placeholder as Title on Picker Item Selection in Xamarin Forms

Need a custom picker in which the Title reduces in size once an Item is selected from the Picker as in image. Same happens for a MaterialisedEntry but need the same for Picker Control
Xamarin.Forms does not allow you to inject a custom view (like a ContentView with a stacklayout) into the Picker control). What you could do is to use a Grid where you have a stacklayout overlaid on a Picker. Based on the SelectedItem property of the picker you would need to update the Text of the State Label.
<Grid HorizontalOptions="Center" VerticalOptions="Center">
<Picker x:Name="picker"
Title="select a state">
<Picker.ItemsSource>
<x:Array Type="{x:Type x:String}">
<x:String>Colorado</x:String>
<x:String>California</x:String>
<x:String>Ohio</x:String>
</x:Array>
</Picker.ItemsSource>
</Picker>
<StackLayout WidthRequest="300" InputTransparent="True" BackgroundColor="White">
<Label Text="State" FontSize="10"/>
<!--Here you would need to bind the Label Text to a property
that changes according to the SelectedItem of the picker-->
<Label Text="Colorado" FontSize="14"/>
</StackLayout>
</Grid>
According to your description, I suggest you can use custom render to add arrow for Picker control, like this:
Create class name CustomPicker in PLC.
public class CustomPicker : Picker
{
public static readonly BindableProperty ImageProperty =
BindableProperty.Create(nameof(Image), typeof(string), typeof(CustomPicker), string.Empty);
public string Image
{
get { return (string)GetValue(ImageProperty); }
set { SetValue(ImageProperty, value); }
}
}
Create class name CustomPickerRenderer in Android or ios.
[assembly: ExportRenderer(typeof(CustomPicker), typeof(CustomPickerRenderer))]
namespace demo3.Droid
{
public class CustomPickerRenderer : PickerRenderer
{
CustomPicker element;
protected override void OnElementChanged(ElementChangedEventArgs<Picker> e)
{
base.OnElementChanged(e);
element = (CustomPicker)this.Element;
if (Control != null && this.Element != null && !string.IsNullOrEmpty(element.Image))
{
Control.Background = AddPickerStyles(element.Image);
}
}
public LayerDrawable AddPickerStyles(string imagePath)
{
//ShapeDrawable border = new ShapeDrawable();
// border.Paint.Color = Android.Graphics.Color.Gray;
// border.SetPadding(10,10,10,10);
// border.Paint.SetStyle(Paint.Style.Stroke);
//Drawable[] layers = { border , GetDrawable(imagePath) };
Drawable[] layers = { GetDrawable(imagePath) };
LayerDrawable layerDrawable = new LayerDrawable(layers);
layerDrawable.SetLayerInset(0, 0, 0, 0, 0);
return layerDrawable;
}
private BitmapDrawable GetDrawable(string imagePath)
{
int resID = Resources.GetIdentifier(imagePath, "drawable", this.Context.PackageName);
var drawable = ContextCompat.GetDrawable(this.Context, resID);
var bitmap = ((BitmapDrawable)drawable).Bitmap;
var result = new BitmapDrawable(Resources, Bitmap.CreateScaledBitmap(bitmap, 70, 70, true));
result.Gravity = Android.Views.GravityFlags.Right;
return result;
}
}
}
3.Reference this customPicker in PLC.
<Frame
Padding="8"
BorderColor="Gray"
CornerRadius="20"
HasShadow="True"
IsClippedToBounds="True">
<StackLayout>
<Label
x:Name="label"
FontSize="20"
Text="state" />
<picker:CustomPicker
x:Name="picker1"
Title="select one item"
Image="ic_arrow_drop_down"
SelectedIndexChanged="Picker1_SelectedIndexChanged">
<picker:CustomPicker.Items>
<x:String>1</x:String>
<x:String>2</x:String>
</picker:CustomPicker.Items>
</picker:CustomPicker>
</StackLayout>
</Frame>
private void Picker1_SelectedIndexChanged(object sender, EventArgs e)
{
var picker = sender as CustomPicker;
if(picker.SelectedIndex>-1)
{
label.FontSize = 10;
}
}
This is the screenshot:

Custom content view with Label-Entry duplicates Xamarin forms

I have custom content view with a Label as title and another Label as detail and an edit Icon ; when the icon is clicked detail label is converted to Entry to make changes and the changes are carried over to binding.
I have bound multiple of these custom views to different properties of same object and trying to edit each one and move to next one, the problem is it seems to duplicate the individual views
I have also put x:Name but still it duplicates same value to the views above it ..
Just the edit of Lastname
Now if I move to 3rd view and edit it , it replicates new value to all previously edited values. - for lastname in this case which is weird considering its not same view used in the page and on debug it hits the method only once.
Custom content view:
<StackLayout Orientation="Horizontal"
VerticalOptions="Start"
Padding="25,10,25,10">
<StackLayout x:Name="stackLayoutDetail"
HorizontalOptions="FillAndExpand">
<Label x:Name="title"
Text="{Binding Title}" />
<Label x:Name="detail"
Text="{Binding Detail}"
FontSize="Large"
FontAttributes="Bold" />
</StackLayout>
<Image x:Name="editIcon"
Source="edit_icon.png"
WidthRequest="25"
HeightRequest="25"
IsVisible="{Binding EditIconVisible}">
<Image.GestureRecognizers>
<TapGestureRecognizer Tapped="EditIcon_Clicked" />
</Image.GestureRecognizers>
</Image>
</StackLayout>
Code behind:
private static Entry newEntry = new Entry();
public static readonly BindableProperty DetailProperty = BindableProperty.Create(propertyName: nameof(Detail),
returnType: typeof(string),
declaringType: typeof(LabelledEntrywithIcon),
defaultValue: default(string));
public string Detail
{
get
{
return (string)GetValue(DetailProperty);
}
set => SetValue(DetailProperty, value);
}
private void EditIcon_Clicked(object sender, System.EventArgs e)
{
detailLabel = (Label)stackLayoutDetail.Children[1];
stackLayoutDetail.Children.RemoveAt(1);
newEntry.Text = Detail;
stackLayoutDetail.Children.Add(newEntry);
editIcon.IsVisible = false;
newEntry.Completed += NewEntry_Completed;
}
private void NewEntry_Completed(object sender, System.EventArgs e)
{
try
{
var _newText = newEntry.Text;
detailLabel.Text = _newText;
stackLayoutDetail.Children.RemoveAt(1);
stackLayoutDetail.Children.Add(detailLabel);
Detail = _newText;
editIcon.IsVisible = true;
}
catch (System.Exception ex)
{
Debug.WriteLine(ex.Message);
}
}
Page
<local:LabelledEntrywithIcon x:Name="firstName"
Title="First Name"
Detail="{Binding Fella.FirstName}" />
<local:LabelledEntrywithIcon x:Name="lastname"
Title="Last Name"
Detail="{Binding Fella.LastName}" />
<local:LabelledEntrywithIcon x:Name="gender"
Title="Gender"
Detail="{Binding Fella.Gender}" />
Code behind:
ViewModel=new MainViewModel();
BindingContext = ViewModel;
Complete code to test is at Github repo : https://github.com/pmahend1/CustomViewDuplicationIssue
Strange but I changed a line of code and it works as expected now.
On the class variables changed private static Entry newEntry= new Entry(); to
private static Entry newEntry;
in EditIcon_Clicked method instead of newEntry.Text = Detail; used
newEntry = new Entry { Text = Detail };
I am not sure why it was taking same reference even though its new Entry for each LabelledEntrywithIcon
Instead of creating a new entry and finding and removing the label and adding the new entry after, you could simplify your problem by:
<StackLayout Orientation="Horizontal"
VerticalOptions="Start"
Padding="25,10,25,10">
<StackLayout x:Name="stackLayoutDetail"
HorizontalOptions="FillAndExpand">
<Label x:Name="title"
Text="{Binding Title}" />
<Label x:Name="detail"
Text="{Binding Detail}"
IsVisible="{Binding ShowLabel}"
FontSize="Large"
FontAttributes="Bold" />
<Entry ... IsVisible="{Binding ShowEntry}" ... />
</StackLayout>
<Image x:Name="editIcon"
Source="edit_icon.png"
WidthRequest="25"
HeightRequest="25"
IsVisible="{Binding ShowLabel}">
<Image.GestureRecognizers>
<TapGestureRecognizer Tapped="EditIcon_Clicked" />
</Image.GestureRecognizers>
</Image>
</StackLayout>
Note that I intentionally wrote ... inside the entry element as Placeholder for all customizations you might want do there (font size, etc...).
Now you add two BindablyProperties (type bool) ShowEntry and ShowLabel, where ShowLabel defaults to true and ShowEntry defaults to false.
Now all you have to do is to adapt your EditIcon_Clicked Event:
private void EditIcon_Clicked(object sender, System.EventArgs e)
{
ShowLabel = false;
ShowEntry = true;
newEntry.Text = Detail;
newEntry.Completed += NewEntry_Completed;
}
And adapt NewEntry_Completed to
private void NewEntry_Completed(object sender, System.EventArgs e)
{
try
{
var _newText = newEntry.Text;
detailLabel.Text = _newText;
ShowLabel = true;
ShowEntry = false;
Detail = _newText;
}
catch (System.Exception ex)
{
Debug.WriteLine(ex.Message);
}
}
Basically this does the same as your solution, however you save yourself from having to push UI Items around in your codebehind and especially the bugs and errors coming with it.

Caliburn.Micro + MaterialToolkitDialog not Open .. : (

with Calibrun.Micro(WPF) + MaterialToolkit,
I tried to open Dialog. but not work..
Could you check my code ? (in GitHub)
Here is small test project.
Click the "Open" button.
this button fired dialog like this.
public async void NewConnection(){
var result = await DialogHost.Show(
new UserControl { DataContext = new TestDialogViewModel() },
"MainDialogHost");
}
Change to gray background( good ), but No dialog.. Why ?
I found a solution.
// MainViewModel.cs
TestDialogViewModel vm;
...
public async void NewConnection()
{
vm = IoC.Get<TestDialogViewModel>();
var dialog = new TestDialogView()
{
DataContext = vm
};
var result = await DialogHost.Show(dialog, "MainDialogHost",
(object sender, DialogOpenedEventArgs eventArgs) =>
{
// pass DialogSession to ViewModel.
// View Model can close own dialog !
vm.dialogSession = eventArgs.Session;
},
(object sender, DialogClosingEventArgs eventArgs) =>
{
Debug.WriteLine($"IPaddress = "+vm.IpAddress);
});
}
and
<!-- in MainView.xaml -->
<materialDesign:DialogHost Identifier="MainDialogHost"
CloseOnClickAway="True"
cal:Message.Attach="[Event DialogClosing]=[Action DialogHost_OnDialogClosing()]"
>
and..
// in TestDialogViewModel
public DialogSession dialogSession;
public void BtnConnect()
{
dialogSession.Close();
}
and..
<!-- in TestDialogView.xaml -->
<StackPanel Margin="20" Orientation="Vertical">
<TextBlock>Input IP Address</TextBlock>
<TextBox Margin="0 20 0 10"
FontSize="28"
HorizontalAlignment="Stretch"
Text="{Binding Path=IpAddress, Mode=TwoWay}"
TextAlignment="Center"/>
<TextBlock Foreground="Red" TextAlignment="Center" HorizontalAlignment="Center"></TextBlock>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<Button Style="{StaticResource MaterialDesignFlatButton}"
cal:Message.Attach="[Event Click]=[Action BtnConnect()]"
IsDefault="True"
Margin="0 8 8 0">
<Button.CommandParameter>
<system:Boolean xmlns:system="clr-namespace:System;assembly=mscorlib">True</system:Boolean>
</Button.CommandParameter>
Connect
</Button>
</StackPanel>
</StackPanel>
Screenshots.
It will help someone Caliburn.Micro user !
: )

Resources