How to wrap long messages using Editor in Xamarin Forms - xamarin.forms

I am using Editor control and wish to wrap long messages (Like Whatsapp).
I have explored few sites and got nothing . If this feature is not yet in Xamarin Forms , can I know any alternative for the same ?
My XAML
<Editor Grid.Row="0" Grid.Column="0" Text="{Binding TextMessage}"
TextColor="{StaticResource StartColor}" HorizontalOptions="FillAndExpand"
FontSize="14" TextChanged="Editor_TextChanged"
FontFamily="{StaticResource DefaultFont}" IsEnabled="True"/>
OUTPUT-

I would first suggest you to use AutoSize property of Editor, so if you want your editor to automatically resize depending on the text length, you should set it to TextChanges, otherwise set it to Disabled(this is default value).
Next thing, if you know that the Editor will be used for chat, you can also set Keyboard property to Chat:
<Editor Text="Enter text here" AutoSize="TextChanges" Keyboard="Chat" />

If I am not mistaken, The Editor control has a property for this called the AutoSize Property which takes the EditorAutoSizeOption enum as an input. Available options are TextChanges and Disabled.
<Editor AutoSize="TextChanges"...
If for some reason this does not work for you then you can use the solution in this forum discussion. by ionixjunior.

For those who are still facing issues, I have a case where the line does not wrap as long as there is no break line (Enter). Solution was to change parent layout from StackLayout to Grid. With grid, now it works.
If you want the height to change dynamically when you have more lines, you can use the above solution:
AutoSize="TextChanges"

Related

How tell command (on page) which control was pressed?

i have a big knot in my brain.
The current Situation is the following:
in my xamarin Forems App i have on some Pages a UserControl (House) witch Contains multiple Controls (Floor) and this has also multiple Controls (Rooms) in it.
This is all working perfectly and i have coll control for each room over a HouseControler Class
On my RoomControl i have:
<Grid.GestureRecognizers>
<TapGestureRecognizer Command="{Binding Source={x:Reference Root}, Path=RoomTappedCommand}" />
</Grid.GestureRecognizers>
this is totally perfekt. and i got my command perfectly fired in the Breakpoint.
But what i want to acheve is to open nut just an alert but a custom Popup with a Navigation from the current Page with the Informations of the Tapped Room.
So in need do pass somehow the informations from the RoomControl up to the Page. But i dont know how.
i would love to read some tipps.
Thank you Guys =)
you can always get a reference to the currently active page using App.Current.MainPage. To display an alert, for example
App.Current.MainPage.DisplayAlert(...);

CollectionView template calls converter incorrectly

Xamarin.Forms 5.0.0.2012, Visual Studio 2019 for Mac 8.10.16
I am encountering a problem (on both iOS and Android, on both emulators and physical devices) trying to call a Converter in the XAML describing a new screen in our app. This is the markup:
<ContentPage
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:internal="clr-namespace:Views.Shared"
x:Class="Views.EditPage">
<ContentPage.Resources>
<internal:PictureNameToImageSourceConverter x:Key="PictureNameToImageSourceConverter" />
</ContentPage.Resources>
...
<CollectionView
x:Name="picturesView"
ItemsLayout="HorizontalList"
HeightRequest="90">
<CollectionView.ItemTemplate>
<DataTemplate>
<Frame HasShadow="False" Padding="5">
<Image
HeightRequest="80"
Source="{Binding Path=., Converter={StaticResource PictureNameToImageSourceConverter}}" />
</Frame>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
The CollectionView.ItemsSource value is set in code to a List<string> instance. When the List has no items, the screen displays correctly. When it does have items the app crashes as the screen appears. If I launch the app attached to the VS debugger, the screen freezes before the crash, and I never get any information.
This converter is well tested and is used several other places in the app with no problem. When I replace the Image with <Label Text="{Binding Path=.}"/> the text items are displayed as expected, so it doesn't look like a binding or Path syntax error.
Is there something I'm not seeing or not aware of in the markup that's causing this? Or can anyone suggest further debugging I haven't thought of?
UPDATE
A breakpoint on the very first line of the converter was never reached.
EDIT in response to comments:
From the EditPage codebehind:
public partial class EditPage : ContentPage
{
internal List<string> PictureNames;
...
protected override void OnAppearing( )
{
base.OnAppearing();
picturesView.ItemsSource = PictureNames;
}
The PictureNames property is actually set by a different Page to which one navigates from the EditPage:
private void saveSelection_Click(object sender, System.EventArgs args)
{
creator.PictureNames = new List<string>();
foreach (SelectableItem<Picture> item in pictureItems)
{
if (item.IsSelected)
{
creator.PictureNames.Add(item.Item.PictureName);
}
}
Navigation.PopAsync();
}
pictureItems is a List acting as a ListView.ItemsSource on that screen, where pictures are selected or unselected.
UPDATE
After much setting of breakpoints, I've determined that the line picturesView.ItemsSource = PictureNames; is where the crash happens. It seems odd that it only happens when the template is showing an Image, but not a Label, seeing that the converter is never actually called.
UPDATE
The trick of adding the delay did get me to the breakpoint. And what I found is more puzzling than ever: The value parameter being passed to the Convert method of our converter is null. This is the case whether coming back from the picture selection screen, or if I set the bound list in response to a Button rather than in OnAppearing, or if I just set it right in the page constructor.
In addition, when setting a breakpoint on the crashing line, when the display element in the template is a Label everything is as expected, but when the display element is an Image the debugger freezes when trying to look at those values. The problem is apparently something about the fact of calling a converter in this precise situation.
I tested that by adding a different converter to the template:
<CollectionView.ItemTemplate>
<DataTemplate>
<Frame HasShadow="False" Padding="5" HeightRequest="{Binding Path=., Converter={StaticResource PictureNameToHeightConverter}}">
<Label Text="{Binding Path=.}" />
</Frame>
</DataTemplate>
</CollectionView.ItemTemplate>
Exactly the same result: The value parameter passed to the Convert method is null even though the same bound value in the same template instance is displayed in the Label. If I set a breakpoint on the line assigning the ItemsSource property as before, the debugger freezes.
UPDATE
Finally beginning to suspect that I'm triggering some corner case bug in the framework, I replaced the CollectionView with a CarouselView, and it works correctly:
<CarouselView
x:Name="picturesView"
HeightRequest="90">
<CarouselView.ItemTemplate>
<DataTemplate>
<Frame HasShadow="False" Padding="5">
<Image
HeightRequest="80"
Source="{Binding Path=., Converter={StaticResource PictureNameToImageSourceConverter}}" />
</Frame>
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
I'm adding this as an update to the question rather than as an answer because I still don't actually know the explanation.
I've seen some odd behavior when updating page details in OnAppearing.
Hard to put a finger on exactly when there will be a problem, but the fact that you navigated to another page, so this is OnAppearing during the "back" from that other page is probably a factor.
Try this:
protected override void OnAppearing( )
{
base.OnAppearing();
Device.BeginInvokeOnMainThread( async () => {
// Let the page appear on screen, before setting ItemsSource.
await System.Threading.Tasks.Task.Delay(200);
picturesView.ItemsSource = PictureNames;
});
}
At minimum, this should allow Xamarin to reach the breakpoint in the converter.
——————-
UPDATE
I don’t see any obvious flaw in the code you’ve posted.
You’ve narrowed it down to the line it crashes on.
Yet a breakpoint at start of converter is never reached.
As you say, this is a puzzling combination of facts.
Here is a test to do:
Put breakpoint on the line that crashes.
Copy the values in the list, to a text editor.
Add a button on the current page, that when pressed, fills the list with those same strings, hardcoded as a literal, then sets the ItemSource.
Start over, but this time press the button - Does this work or crash?
That is, remove all the complexity of going to another page, querying values, returning to this page.
I bet this will work. Then you’d have the best situation for debugging: a case that works vs. one that doesn’t.
After that, its “divide and conquer”. Start making the working one more like the broken one, and/or vice versa, until the culprit is identified.
You could try to pass data with the ways below when you do the navigation.
One way is to set the BindingContext to the page which you want to navigate to.
Use the Navigation.PushAsync to navigate the page and reset the BindingContext before the page navigated. You could check the thread i done before for more details. Xamarin Public Class data how to acess it properly
Or you could try to binding to a path property using MVVM.
<Image HeightRequest="80" Source="{Binding path, Converter={StaticResource PictureNameToImageSourceConverter}}" />
Another way is to pass the data to the page which you want to navigate through a Page Constructor.
For more details of this way, check the MS docs. https://learn.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/navigation/hierarchical#passing-data-through-a-page-constructor
While it would be interesting to know why the CollectionView binding isn't behaving as expected in this specific situation, the number of hours spent trying to figure it out has definitely passed the point of diminishing returns, so I just added the images the old-fashioned way. I replaced the CollectionView with a StackLayout:
<StackLayout x:Name="picturesLayout" Orientation="Horizontal" />
And then just added framed images "by hand" in the OnAppearing method:
picturesLayout.Children.Clear();
foreach (string pictureName in PictureNames)
{
picturesLayout.Children.Add(new Frame { Padding = 5, HasShadow = false, Content = new Image { Source = ImageManager.ReadFromDisk(pictureName), HeightRequest = 80 } });
}
(ImageManager handles chores like keeping track of the full path to the appropriate directory.)

Xamarin.Forms, Set MaxLines in editor

I have an editor:
<Editor
Margin="10,0,10,10"
x:Name="entry_descri_pickcate"
FontFamily="arial"
MaxLength="190"
FontSize="14"
TextColor="#dfdfdf"
BackgroundColor="#00000000"
PlaceholderColor="#dfdfdf"
Placeholder="Beschreibung ..."
/>
This editor has a max length property but not a max lines property. This causes anyone to destroy our layout. It is not our goal do disable line breaks, but at some point a new line must be forbidden.
How do I achieve that?
Thank you
The MaxLines property for now is not supported. But it would be reported on GitHub.
https://github.com/xamarin/Xamarin.Forms/issues/10689
This feature has be added to Enhancement. Please follow the progress.

Is it possible to hide a specific FlyoutItem when using Xamarin Forms Shell?

I am using Xamarin Forms Shell and I want to be able to hide some items of my Flyout depending on some parameters (the current page for instance) but I can't find any method or property to change the visibility of a FlyoutItem.
Is it possible to programmaticaly hide some FlyoutItem (not the complete Flyout just some items) ?
As of this moment it is not possible, there is a current Issue regarding this.
However, I managed to find another thread, where there might be a solution with dynamic creating flyout items. You can check it here.
It is possible with Xamarin.Forms 4.8 version.
you can use Isvisible attribute to show/hide any flyout item.
Please refer below link for more details :
Xamarin.Forms v4.8
GitHub Issue Resolved
Had the same issue, here is my solution.
I created a style, and set that to hidden.
Then I update my MenuItem in the backend, depending what is needed.
Style
<Style
ApplyToDerivedTypes="True"
Class="MenuItemLayoutStyleHidden"
TargetType="Layout">
<Setter Property="IsVisible" Value="False" />
</Style>
Menu Item
<MenuItem
x:Name="btnLogout"
Clicked="btnLogoutClick"
IconImageSource="icon_about.png"
StyleClass="MenuItemLayoutStyle"
Text="Logout" />
Backend Code
if (user.isLoggedIn)
{
btnLogout.#class.Clear();
btnLogout.#class.Add("MenuItemLayoutStyle");
}
else
{
btnLogout.#class.Clear();
btnLogout.#class.Add("MenuItemLayoutStyleHidden");
}
this works for me
flyoutxname.FlyoutItemIsVisible = false;
where flyoutxname is the x:Name property for the flyoutitem.
<FlyoutItem Title="item title" x:Name="flyoutxname" Icon="byebye.jpg">
source
https://learn.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/shell/flyout
I was searching how i can hide a MenuItem in Shell Flyout because i didn't want to use FlyoutItem. I needed the Clicked event. I managed to hide a MenuItem with:
<MenuItem Text="Arrivals" x:Name="Arrivals" Clicked="MenuItem_Clicked" Shell.FlyoutItemIsVisible="False"/>

In custom WorkflowViewElement, how to support WF4.5 Annotations?

I've created a a custom activity designer, but I wanted to have control over the 'header' part (that by default shows the ModelItem.DisplayName), and as far I know, the only way to achieve this is to derive the designer from WorkflowViewElement rather than ActivityDesigner. So, that seems to work and all is well. Except, I want to support the new Annotations feature of WF4.5.
Given that when you add an annotation to a workflow element on the design surface it adds an icon to the element you are annotating + the actual annotation element, it seems clear that any custom WorkflowViewElement has to have some extra stuff in it to support this behaviour. Can anyone help?
Thanks
As I thought, annotations are saved within the workflow definition as an attached property. Here's what an annotation looks like in the workflow's xaml:
<Sequence
xmlns:derp="http://schemas.microsoft.com/netfx/2010/xaml/activities/presentation"
derp:Annotation.AnnotationText="This is an annotation!">
See, just like any other attached property. Except it isn't. Its an attached workflow property, not an attached DependencyProperty. That means it works through the attached property service as well as the Annotation class. Getting and setting the annotation text on a ModelItem is trivial (and covered below).
Its actually not that hard to support annotations. As long as you don't mind your UI looking like crap. Here's a quick and dirty implementation.
In the UI, add some controls for holding and editing the annotation text
<sap:WorkflowViewElement
x:Class="AnnotationSupport.MyActivityDesigner"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sap="clr-namespace:System.Activities.Presentation;assembly=System.Activities.Presentation"
xmlns:ann="clr-namespace:System.Activities.Presentation.Annotations;assembly=System.Activities.Presentation"
xmlns:sapv="clr-namespace:System.Activities.Presentation.View;assembly=System.Activities.Presentation"
x:Name="root"
MinWidth="100"
MinHeight="100">
<Grid Background="red">
<Grid.RowDefinitions>
<RowDefinition
Height="auto" />
<RowDefinition />
</Grid.RowDefinitions>
<Expander
IsExpanded="False">
<!-- HERE SHE BLOWS -->
<TextBox
Text="{Binding ModelItem.AnnotationText}" />
</Expander>
<TextBox
Grid.Row="1"
Text="{Binding ModelItem.Text}"
Margin="10" />
</Grid>
</sap:WorkflowViewElement>
Any time the Annotation text changes, the ModelItem's PropertyChanged event fires, just like any other property. And if you want to grab it from code, the simplest way is to cast the ModelItem to a dynamic:
private void SetAnnotationLol(string newValue)
{
if(ModelItem != null)
((dynamic)ModelItem).AnnotationText = newValue;
}
Now, if you want to create a nice UI like the Fx Activities have... well...
I'll leave it up to you to create a custom Adorner to handle display and editing of the annotation. Which actually isn't as hard as it first looks. If you haven't done one yet, here's your opportunity.

Resources