I'm working on a chat application using Xamarin.Forms.
And I want to avoid to hide the keyboard when the Entry loses focus and button Send is clicked.
How can I do it on Android and iOS?
I use XF, full Mvvm without XAML(only C#)
Updated:
In page class:
private EntrySetBorder _newMessageEntry;
...
_newMessageEntry = new EntrySetBorder
{
TextColor = Color.Black,
HorizontalOptions = LayoutOptions.FillAndExpand,
VerticalOptions = LayoutOptions.End,
Margin = new Thickness(0, 0, 5, 0)
};
In model class:
var entry = CurrentPage.FindByName<EntrySetBorder>("_newMessageEntry");
entry.Focus();
}
This can be achieved easily by using the FindByName<>() function inside the PCL.
This is one way of doing that:
Entry myEntry = CurrentPage.FindByName<Entry>("YourEntryName");
myEntry.Focus();
You can add that at the end of the click handler of your send button.
Edit:
In your case I think your problem is that your entry is set to private, so I would suggest either expose it as public or expose it using another public property. Two solutions that might work:
public EntrySetBorder _newMessageEntry;
...
_newMessageEntry = new EntrySetBorder
{
TextColor = Color.Black,
HorizontalOptions = LayoutOptions.FillAndExpand,
VerticalOptions = LayoutOptions.End,
Margin = new Thickness(0, 0, 5, 0)
};
And:
EntrySetBorder entry = CurrentPage.FindByName<EntrySetBorder>("_newMessageEntry");
entry.Focus();
Or you go with this:
private EntrySetBorder _newMessageEntry;
...
_newMessageEntry = new EntrySetBorder
{
TextColor = Color.Black,
HorizontalOptions = LayoutOptions.FillAndExpand,
VerticalOptions = LayoutOptions.End,
Margin = new Thickness(0, 0, 5, 0)
};
public EntrySetBorder NewMessageEntry => _newMessageEntry;
and :
EntrySetBorder entry = CurrentPage.FindByName<EntrySetBorder>("NewMessageEntry");
entry.Focus();
Please try that :)
Edit 2:
After reviewing your code, and testing it, the final way to fix it was by sending the Entry as a parameter in the command you're using, example:
Inside the page you're creating:
sendButton.CommandParameter = NewMessageEntry; // We're adding the Entry we want to focus as a command parameter.
And inside your PageModel and the command we want to use:
public Command SendCommand
{
get
{
return new Command<Entry>((obj) => //obj here means the parameters we're sending I.E: the entry we set it in the page.
{
//The code you want to execute
Entry entry = obj;
entry.Focus();
});
}
}
Note that I used Entry because I didn't have all the implementation of your custom entry.
This is an example of how I do, before this I used to do using MessagingCenter
in xaml , you need to give an x:Name to the obj you want to make focus.
<!-- PICKER's DEFINITION -->
<DatePicker
x:Name="Datepicker"
Date="{Binding SelectedDate, Mode=TwoWay}"
IsEnabled="true"
IsVisible="false">
</DatePicker>
then you have to make reference to that control in your command parameter on a button or for example in this case I use a toolbar item.
<!-- MENU TOOLBAR -->
<ContentPage.ToolbarItems>
<ToolbarItem
Command="{Binding ShowCalendarCommand}"
Icon="Calendar"
CommandParameter="{x:Reference Datepicker}" />
</ContentPage.ToolbarItems>
then in your vm command :
#region toolbar commands
public ICommand ShowCalendarCommand => new RelayCommand<Object>(ShowCalendar);
#endregion
private void ShowCalendar(Object obj)
{
var calendar = (DatePicker)obj;
calendar.Focus();
// MessagingCenter.Send(this, "Calendar");
}
Related
I understand how this code works but can someone explain what the first line does? Is this translated some place into some C# code. How about if I wanted to code this manually, how could I go about that?
[Xamarin.Forms.ContentProperty("Contents")]
class PopupFrame : Frame
{
StackLayout contentStack { get; } = new StackLayout();
public IList<View> Contents { get => contentStack.Children; }
public PopupFrame()
{
Content = contentStack;
HasShadow = true;
HorizontalOptions = LayoutOptions.FillAndExpand;
Padding = 0;
VerticalOptions = LayoutOptions.Center;
}
}
This attribute tells the XAML processor that if should use the Frame's Content property as the default basically. So, in practice it allows you to write this
<ContentView>
<Label Text="Hello, Forms"/>
</ContentView>
Instead of
<ContentView>
<ContentView.Content>
<Label Text="Hello, Forms"/>
</ContentView.Content>
</ContentView>
Examples taken from the Docs page.
In regard to your question "how do I write this in C#?" you don't. This is something specific to XAML and nothing more than syntactic sugar. In C# you would simply assign something to the Content property. I.e.:
var frame = new Frame();
Frame.Content = new Label() { Text = "Hello, Forms" };
I am building an C# UWP application where onclick of a button in the view a command (using System.Windows.Input.IComand) raises in viewmodel(not code behind) which builds a form of input fields like Name:____ phone:____ etc and shows it on the UI/view.
I dont want to keep the <ContentDialog></ContentDialog> in the
view.
What have I done so far is
Button in my view:
<CommandBar>
<AppBarButton x:Name="buttonNew" Command="{Binding AddClick}" />
</CommandBar>
ViewModel object in the code behind is set as the DataContext of the
View
In the view model:
public ICommand AddClick=> new RelayCommand(Add);
private async void Add()
{
TextBox input = new TextBox()
{
PlaceholderText = "Name",
};
var contentDialog = new ContentDialog
{
Title = "Add a Person",
Content = input,
FullSizeDesired = true,
PrimaryButtonText = "Add",
CloseButtonText = "Cancel"
};
await contentDialog.ShowAsync();
}
As you can see I am able to show/trigger a Content Dialog box with one input field and 2 buttons.
My problem is:
How to add more input fields like we add in a
<StackPanel></StackPanel> in the code of view model and assign it
to the content of the Content Dialog?
How to size it accordingly that all the fields show up properly and does not show up haphazard since am not coding this in the Xaml?
From the general application construction practice, it is recommended to create a UI using XAML to create a custom ContentDialog.
You don’t have to write the XAML code of ContentDialog in the View, you can add new item in Visual Studio, select the Content Dialog template, and create a custom dialog derived from ContentDialog.
Then use code similar to the following:
MyCustomDialog.xaml
<ContentDialog
...
Title="Add a Person"
FullSizeDesired="True"
PrimaryButtonText="Add"
CloseButtonText="Cancel"
PrimaryButtonClick="ContentDialog_PrimaryButtonClick">
<StackPanel>
<TextBox Header="Name" x:Name="NameBox" PlaceholderText="Name"
HorizontalAlignment="Stretch"/>
<TextBox Header="Phone" x:Name="PhoneBox" PlaceholderText="Phone"
Margin="0,15,0,0" HorizontalAlignment="Stretch"
InputScope="Number"/>
</StackPanel>
</ContentDialog>
ViewModel.cs
private async void Add()
{
var dialog = new MyCustomDialog();
await dialog.ShowAsync();
}
If you insist on using C# code to create ContentDialog, you need to convert the tags in XAML into corresponding classes, but this method is not easy to debug.
private async void Add()
{
var container = new StackPanel();
TextBox nameBox = new TextBox()
{
PlaceholderText = "Name",
Header = "Name",
HorizontalAlignment = HorizontalAlignment.Stretch
};
TextBox phoneBox = new TextBox()
{
PlaceholderText = "Phone",
Header = "Phone",
HorizontalAlignment = HorizontalAlignment.Stretch,
Margin = new Thickness(0, 15, 0, 0)
};
container.Children.Add(nameBox);
container.Children.Add(phoneBox);
var contentDialog = new ContentDialog
{
Title = "Add a Person",
Content = container,
FullSizeDesired = true,
PrimaryButtonText = "Add",
CloseButtonText = "Cancel"
};
await contentDialog.ShowAsync();
}
The tags in XAML are actually the corresponding classes in C#, from the code you provided, the ContentDialog is displayed in full screen. You mentioned that you want the fields to be displayed correctly, if you mean that the string entered in the TextBox is too long and the text is not displayed completely, you can set the TextBox.TextWrapping property to True.
In My Project,I Create Some Images with C# and i want these photo's sources, Bind to a property in My ViewModel.
in My MVVM :
public event PropertyChangedEventHandler PropertyChanged = delegate { };
private string _Light= "dark.png";
public string Light
{
get { return _Light; }
set {
_Light = value;
PropertyChanged(this, new PropertyChangedEventArgs(nameof(Light)));
}
}
in My C#:
BindingContext = new LightViewModel();
LightViewModel light = new LightViewModel();
Image dark = new Image { Margin = new Thickness(0, -5, 0, 10), HeightRequest = 20, WidthRequest = 20 };
dark.SetBinding(Image.SourceProperty, light.Light);
i use exactly this MVVM with this Xaml, and it's Property work
<Image Source="{Binding Light}" ></Image>
Can help me :)
Actually, the second parameter of SetBinding method is the name of the property, not the property itself, so what you should do is something like this:
dark.SetBinding(Image.SourceProperty, "Light");
I have a tab control in which I am adding tab items programmatically. I want to have a close button with each tab item. On googling I found below XAML code for it:
<Button Content="X" Cursor="Hand" DockPanel.Dock="Right"
Focusable="False" FontFamily="Courier" FontSize="9"
FontWeight="Bold" Margin="5,0,0,0" Width="16" Height="16" />
Now, I am converting this code into equivalent C# code and struggling with some of the properties. Below given is the code which I have till now.
var CloseButton = new Button()
{
Content = "X",
Focusable = false,
FontFamily = FontFamily = new System.Windows.Media.FontFamily("Courier"),
FontSize = 9,
Margin = new Thickness(5, 0, 0, 0),
Width = 16,
Height = 16
};
I want help with properties like Cursor, DockPanel.Dock. Any help on this is much appreciated. Thanks !
Cursors are a fairly standard set of types. There are static classes out there that give you access to many of them. Use the Cursors class to get the Hand.
DockPanel.Dock is an attached property, it's not a property of the button control. You have to use the property setters for that dependency object or other convenience methods if available.
var button = new Button
{
Content = "X",
Cursor = Cursors.Hand,
Focusable = false,
FontFamily = new FontFamily("Courier"),
FontSize = 9,
Margin = new Thickness(5, 0, 0, 0),
Width = 16,
Height = 16
};
// this is how the framework typically sets values on objects
button.SetValue(DockPanel.DockProperty, Dock.Right);
// or using the convenience method provided by the owning `DockPanel`
DockPanel.SetDock(button, Dock.Right);
Then to set the bindings, create the appropriate binding object and pass it to the element's SetBinding method:
button.SetBinding(Button.CommandProperty, new Binding("DataContext.CloseCommand")
{
RelativeSource = new RelativeSource { AncestorType = typeof(TabControl) },
});
button.SetBinding(Button.CommandParameterProperty, new Binding("Header"));
I want to add a number of TextBlocks inside a Button. How can I add a number of them, along with StackPanels or Canvases, in C#, as shown below in XAMAL
<Button>
<StackPanel>
<TextBlock Text="ABC"/>
<TextBlock Text="DEF"/>
</StackPanel>
</Button>
It's easy:
public partial class MainWindow : Window {
public MainWindow() {
InitializeComponent();
var tb1 = new TextBlock() { Text = "TextBlock 1" };
var tb2 = new TextBlock() { Text = "TextBlock 2" };
var stackPanel = new StackPanel();
stackPanel.Children.Add(tb1);
stackPanel.Children.Add(tb2);
var button = new Button() { Content = stackPanel };
this.Content = button;
}
}
Maybe you should think about an enclosing control of csharpfolk's answer. This would help to get a reuseable control.
The text strings are good to use as a dependency property. :)
Regards,
- Tobbo