I have label that is bound to my view model. Sometimes the text value of the label is only a few characters, but sometimes it is more than 20 characters.
How to limit maximum length of label text?
Check out the LineBreakMode property:
https://learn.microsoft.com/en-us/dotnet/api/xamarin.forms.label.linebreakmode?view=xamarin-forms
You can set your Label's LineBreakMode to TailTruncation to make the Label truncate any characters that don't fit in its allotted space and replace them with ellipses.
<Label Text="{Binding LabelText}" LineBreakMode="TailTruncation" />
Then you just need to limit the allotted width of the Label to an acceptable size. How you do that will depend on your specific scenario.
You can use a converter:
public class LabelMaxLengthConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
string labelText = value as string;
if (labelText == null)
return value;
const int maxLength = 20;
if (labelText.Length > maxLength)
return labelText.Substring(0, maxLength);
else
return labelText;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
And in your xaml first define that converter in pages's resouurces:
<ContentPage.Resources>
<converters:LabelMaxLengthConverter x:Key="LabelMaxLengthConverter" />
</ContentPage.Resources>
And finally in your label apply the converter to binding:
<Label Text="{Binding LabelText, Converter={StaticResource LabelMaxLengthConverter}}" />
Related
I a have typical label that I want to control its visibility by a property that is null/empty or not.
I've put breakpoints and also log and it seems that return value is true but still it does not show the element. When I scroll my listview then they are visible but sometimes still not.. There are several items, sometimes some of them are visible sometimes not.. it is changable..
here my converter
public class TestBooleanConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var result= value != null && !value.ToString().Equals("");
Console.WriteLine("Result: " +result);
return result;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
and the property
public string LocalizedReadoutDescription
{
get
{
Console.WriteLine("Description: " + dataItem.Description);
string localizedDescription = null;
if (!string.IsNullOrEmpty(this.dataItem.Description))
{
string[] descriptionKeyParts = this.dataItem.Description.Split(';');
localizedDescription = descriptionKeyParts[0];
if (!string.IsNullOrEmpty(localizedDescription))
{
localizedDescription =
this.getLocalizedString(Constants.Localization.LogicalItemDescriptionFmt,
localizedDescription);
}
}
return localizedDescription;
}
}
and Xaml Code
<ContentView.Resources>
<converters:TestBooleanConverter x:Key="nullToBoolConverter"/>
.....
</ContentView.Resources>
.....
<StackLayout Orientation="Horizontal" Margin="4,2" Grid.Column="1" VerticalOptions="StartAndExpand"
HorizontalOptions="FillAndExpand" Spacing="0" BackgroundColor="White">
<StackLayout.GestureRecognizers>
<TapGestureRecognizer Tapped="Help_Tapped" CommandParameter="{Binding}"/>
</StackLayout.GestureRecognizers>
<Label x:Name="HelpLabel" Style="{StaticResource InfoIconLabel}" Text="{x:Static resx:UI.Icon_Info}" Margin="0"
HorizontalOptions="EndAndExpand" VerticalOptions="Start" IsVisible="{Binding LocalizedReadoutDescription,
Converter={StaticResource nullToBoolConverter}}" FontSize="Micro" LineBreakMode="NoWrap"/>
</StackLayout>
I feel that, even it returns true, but it uses the previous rows value. but only this part does not update. label names, values are updated, but only some items' visibility is not updating..
where is my mistake?
Update:
I've created an event for property change of the label that I want to control its visibility. I can see that, the IsVisible is always true but on the GUI, only one item is visible.. but when I scroll, several are visible, and when I scroll more then all items are visible as it must be
private void HelpLabel_OnPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName.Equals("IsVisible"))
{
// I check => ((Xamarin.Forms.Label)sender).IsVisible
//always true
}
}
I have found the problem. It was not regarding cache or informing UI element. Somehow it was regarding the item's height. I've gave a height and heightrequest value, and then it works always.. weird..
I have a model like:
{
"images": [{
"image_url": "..........",
"orientation": "horizontal"
},
{
"image_url": "...............",
"orientation": "vertical"
}]
}
and a ListView DataTemplate
<DataTemplate x:DataType="model:ImageItem">
<controls:ImageEx Source="{x:Bind cover_image_url}" PlaceholderSource="" PlaceholderStretch="Uniform"/>
</DataTemplate>
Now, I want the ImageEx control's PlaceholderSource property change along with orientation.
More clearly, when the image property is horizontal, ImageEx will load a place holder 1. When the image property is vertical, ImageEx will load a place holder 2.
How to do this. Please show me.
More clearly, when the image property is horizontal, ImageEx will load a place holder 1. When the image property is vertical, ImageEx will load a place holder 2.
You could use IValueConverter interface to approach, use converter class to converter different message type to different PlaceholderSource for ImageEx. You could refer the follow ImageConverter.
public class ImageConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
object img = null;
switch (value.ToString())
{
case "horizontal":
img = new BitmapImage(new Uri("ms-appx:///Assets/holder1.png"));
break;
case "vertical":
img = new BitmapImage(new Uri("ms-appx:///Assets/holder2.png"));
break;
default:
break;
}
return img;
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotImplementedException();
}
}
Xaml
<Page.Resources>
<local:ImageConverter x:Key="Converter"/>
</Page.Resources>
......
<DataTemplate x:DataType="model:ImageItem">
<controls:ImageEx Source="{x:Bind cover_image_url}" PlaceholderSource="{x:Bind orientation,Converter={StaticResource Converter}}" PlaceholderStretch="Uniform"/>
</DataTemplate>
In the ListView, I need to show some images and text, only display the text when the Image.Source is empty. How to do?
<ListView ItemsSource="{x:Bind ViewModel.News}">
<ListView.ItemTemplate>
<DataTemplate x:DataType="home:NormalNews">
<StackPanel>
<TextBlock Text="{x:Bind Title}"/>
<Image Source="{x:Bind Thumbnail}"/>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
ViewModel Data Source like:
News.Add(new NormalNews{ Title = "title1", Thumbnail = "http://a.com/test.jpg" });
News.Add(new NormalNews{ Title = "title2", Thumbnail = "" });
When I tried to run this page, it stopped running.
You can handle this using xaml converters.
Add a converter and define a key for it in your page.
In XAML page
<converter:ImageUriConverter x:Key="ImageUriConvert"/>
In your list
<Image Source="{Binding Thumbnail,Converter={StaticResource ImageUriConvert}}"/>
Converter class code
class ImageUriConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
if (value.ToString() == string.Empty)
{
return new BitmapImage();
}
return new BitmapImage(new Uri(value.ToString()));
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotImplementedException();
}
}
While you are populating the ViewModel object, do this:
ViewModel.News.Add(new NormalNews{
Thumbnail=(the Thumbnail source which you will be using),
Title=(the Thumbnail source which you will be using)==""?"Your Title":""});
This will set your Title to the specified string when your Thumbnail source is empty.
Hope this helps.
I would like to set the bottom Corner Radius of a ListView Item for just the "last" item in the list. I've attempted to do so with a Converter (which in fact finds the last row), but to no avail.
The desirable effect is when the Converter returns true after finding the last item in the ListView, the border CornerRadius on the last ListViewItem is set to CornerRadius="0,0,10,10". For all other items in the ListView, CornerRadius="0,0,0,0"
What I've done so far.
The Converter...
public class IsLastItemConverter : IValueConverter
{
#region IValueConverter Members
public object TrueValue { get; set; }
public object FalseValue { get; set; }
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
ListViewItem item = value as ListViewItem;
ListView listView = ItemsControl.ItemsControlFromItemContainer(item) as ListView;
if (listView != null)
{
int index = listView.ItemContainerGenerator.IndexFromContainer(item);
if (index == listView.Items.Count - 1)
{
TrueValue = true;
return (bool)TrueValue;
}
else
{
FalseValue = false;
return (bool)FalseValue;
}
}
FalseValue = false;
return (bool)FalseValue;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
// Just Convert Back
return true;
}
#endregion
}
The XAML...
<local:IsLastItemConverter x:Key="lastItemConverter"
TrueValue="0,0,10,10" FalseValue="0,0,0,0"/>
<DataTemplate x:Key="CellContentTemplate">
<Border
x:Name="CellContentBorder"
Background="{StaticResource GrayCharcoal}"
BorderThickness="4,4,4,4"
BorderBrush="{StaticResource Gray}"
CornerRadius="{Binding Converter={StaticResource lastItemConverter},
RelativeSource={RelativeSource AncestorType={x:Type ListViewItem}}}"
HorizontalAlignment="Left"
Width="210"
Height="50"
ContextMenu="{StaticResource MarginalUnitsContextMenu}"
ScrollViewer.VerticalScrollBarVisibility="Hidden">...
Thoughts and ideas much appreciated - Glenn
I would try returning a real CornerRadius instead of a string (which, you are essentially returning).
My assumption is following:
When passing as string "0,0,0,0" in xaml as CornerRadius, the appropriate Converter is used to convert this string in to a CornerRadius struct.
As you are now using a custom converter, possibly the string to CornerRadius Converter is not anymore used...
EDIT (in light of Clemens answer): The Converter for the property does seem to kick in when a string was returned from the custom converter associated with the binding!
This is because CornerRadius has an associated TypeConverter:
[TypeConverterAttribute(typeof(CornerRadiusConverter))]
public struct CornerRadius : IEquatable<CornerRadius>
which handles this conversion. This converter handles the Conversion from string to CornerRadius.
(Taken from http://msdn.microsoft.com/en-us/library/system.componentmodel.typeconverterattribute.aspx )
I am pulling data from a previous page which was a selected item in a listbox from a wcf service.
Ther error I am having is that the textblock is not reading the formatting in my in my data.
this is the code that brings the data in from the previous page
private void LoadPlayer()
{
FrameworkElement root1 = Application.Current.RootVisual as FrameworkElement;
var currentPlayer = root1.DataContext as PlayerProfile;
_SelectedPlayer = currentPlayer;
}
this is the xaml
<TextBlock Height="Auto" TextWrapping="Wrap" Name="Blurb" Text="{Binding Bio}" xml:space="preserve" />
specifically I am trying to get the \r\n to work in my display as a linebreak.
See the answer here:
Newline in string attribute
In your case what you need to do write a Converter (something that implements IValueConverter) that turns the string data that contains the \r\n into encoded entities i.e.
and
. Then just use that converter on your Binding.
public class EncodeCRLFConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
string stringtoconvert = value as string;
if (input != null))
{
// Note there are different ways to do the replacement, this is
// just a very simplistic method.
stringtoconvert = stringtoconvert.Replace( "\r", "
" );
stringtoconvert = stringtoconvert.Replace( "\n", "
" );
return stringtoconvert;
}
return null;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new Exception("The method or operation is not implemented.");
}
}
Create an instance of your converter somewhere...e.g. typically in .Resources....(in this example I've just used Window because I don't know what your TextBlock is inside).
<Window.Resources>
<EncodeCRLFConverter x:Key="strconv"/>
<Window.Resources>
<TextBlock Height="Auto" TextWrapping="Wrap" Name="Blurb" Text="{Binding Bio, Converter={StaticResource strconv}}" />