Create custom frame in xamarin forms - xamarin

I have to create a frame like in the attached photo ,the thing is that it has to be adaptable as it will contain labels/texts , also it should have elevation and shadow .
All that is easily doable with a frame , the problem is the little speech thing , i can't find a way to make it .
maybe someone has an idea to start with .
thanks

You can binding the Height and Width of the frame with its child element (like label).
in code behind
public class SizeConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return ((double)value + 20.0); // you can set the logic of height and width here
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return 0;
}
}
in xaml
<ContentPage.Resources>
<ResourceDictionary>
<local:SizeConverter x:Key="SizeConverter" />
</ResourceDictionary>
</ContentPage.Resources>
<StackLayout VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
<Frame CornerRadius="10" WidthRequest="{Binding Source={x:Reference contentLabel}, Path=Width,Converter={StaticResource SizeConverter} ,Mode=OneWay}" MinimumHeightRequest="100" HeightRequest="{Binding Source={x:Reference contentLabel}, Path=Height,Converter={StaticResource SizeConverter} ,Mode=OneWay}" BackgroundColor="LightBlue" Padding="10" >
<!-- Place new controls here -->
<Label x:Name="contentLabel" BackgroundColor="LightGray" Text="xxx"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand" />
</Frame>
</StackLayout>

Related

Xamarin Binding fuction as ImageSource inside a Listview with Databinding

I'm trying to visualize the state of an object, called MinRepresentation, in the ListView below.
I want to bind the function ImageSource stateImage(MinRepresentationState state), where i handover the state and get back the Imagesource.
My Problem is, accsessing the function and passing the parameter via xaml.
Visible Orders is an Collection of MinRepresentation each includes State
<ListView HasUnevenRows="True" SelectionMode="Single" ItemsSource="{Binding VisibleOrders}" ItemSelected="OnListViewItemSelected" ItemTapped="OnListViewItemTapped">
***OTHER STUFF***
<StackLayout Orientation="Horizontal" Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="3" Padding= "0,5,0,5" BackgroundColor="#CC3F6E3F">
<Image Source="{Binding stateImage(State)" Margin="10,0,0,0" />
<Label Text="{Binding Id, StringFormat='ID: [{0}]'}" FontSize="Small" Margin="5,0,0,0" FontAttributes="Bold" TextColor="#FFFFFF"/>
</StackLayout>
***OTHER STUFF***
</ListView>
public ImageSource stateImage(MinRepresentationState state)
{
switch (state)
{
case MinRepresentationState.Assigned:
return ImageSource.FromResource("state_assigned.png");
}
}
You can use IValueConverter to achieve that. Create an IValueConverter class and place your logic code there:
public class StateToImageConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
MinRepresentationState representationState = (MinRepresentationState)value;
if (representationState == MinRepresentationState.Assigned)
{
return "state_assigned.png";
}
return "otherImage.png";
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
Then consume it in XAML like:
<!--Define it in resources-->
<ContentPage.Resources>
<local:StateToImageConverter x:Key="StateToImageConverter"/>
</ContentPage.Resources>
<!--Use converter-->
<Image Source="{Binding State, Converter={StaticResource StateToImageConverter}}" Margin="10,0,0,0"/>
You can only bind to public properties. Create a StateImage property on your model
public string StateImage
{
get {
switch (State)
{
case MinRepresentationState.Assigned:
return "state_assigned.png";
}
}
}
You could also use a DataTrigger to set the image in your XAML
<Image Source="state_default.png" Margin="10,0,0,0">
<Image.Triggers>
<DataTrigger TargetType="Image" Binding="{Binding State}" Value="Assigned">
<Setter Property="Source" Value="state_assigned.png" />
</DataTrigger>
</Image.Triggers>
</Image>
Reference: https://learn.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/triggers#data

In Xamarin, how do you scale an image without having it take up the same amount of space as it would unscaled?

How do you scale an image and not have it take up the full width/height of the unscaled image? In this simple example I want my image to be 25% of the width and height of the container it is in.
<AbsoluteLayout>
<Image
AbsoluteLayout.LayoutFlags="All" AbsoluteLayout.LayoutBounds="0, 0, .25, .25"
Source="{Binding NiceImage}" />
</AbsoluteLayout>
That does scale the image but the image still takes up the same amount of space as the unscaled image. Aspect doesn't seem to work for this.
You can bind the WidthRequest of the image to that of the parent container, but scaled with a value converter.
If you create a value converter that looks like:
public class CoefConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
double coef = 1.0;
if (parameter is string)
coef = double.Parse(parameter as string);
return (double)value * coef;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
You can use it in the markup like so:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:ScaleImage"
x:Class="ScaleImage.MainPage">
<ContentPage.Resources>
<ResourceDictionary>
<local:CoefConverter x:Key="cc" />
</ResourceDictionary>
</ContentPage.Resources>
<StackLayout x:Name="theStack">
<Image Source="mountain.jpg" Aspect="AspectFit" HorizontalOptions="Start"
WidthRequest="{Binding Source={x:Reference theStack}, Path=Width, Converter={StaticResource cc}, ConverterParameter=0.25}" />
<Label Text="This is some text!" FontSize="Medium" />
</StackLayout>
</ContentPage>
In essence you're setting the WidthRequest of the Image to that of the parent (named theStack) but multiplied by 0.25.
I posted an example here:
https://github.com/curtisshipley/ScaleImageConverter
Try replacing the AbsoluteLayout with a Grid with proportional columns.
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="3*" />
</Grid.ColumnDefinitions>
<Image Source="{Binding NiceImage}" Aspect="AspectFit" Grid.Column="0" />
</Grid>

How can I link a switch and a visible property by binding with a ViewModel?

I have a switch and a label on my XAML page:
<Switch x:Name="CpSwitch" Toggled="CpSwitch" />
<ViewCell x:Name="aBtn" Tapped="openPicker">
<Grid VerticalOptions="CenterAndExpand" Padding="20, 0">
<Label Text="Don't Know" />
<Picker x:Name="aBtnPicker" SelectedIndexChanged="aBtnPickerSelectedIndexChanged" ItemsSource="{Binding Points}">
</Picker>
<Label Text="{Binding ABtnLabel}"/>
</Grid>
</ViewCell>
My ViewModel
public class SettingsViewModel: ObservableProperty
{
public SettingsViewModel()
{
}
What I would like to do is to use a ViewModel and in that view model have the switched state either make the ViewCell visible or not.
Can someone give me some suggestions on how I can bind the switch and the visible property for the ViewCell using a ViewModel.
Basically you bind them both to the same Boolean variable in your view model.
<Switch IsToggled="{Binding ShowViewCell}" />
<ViewCell IsVisible="{Binding ShowViewCell}">
...
</ViewCell>
And in your view model:
public class SettingsViewModel
{
public bool ShowViewCell {get;set;}
}
This ensures that when the Switch is turned ON the ViewCell becomes visible. If you want to achieve the opposite you could write a custom converter:
public class InverseBoolConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return !(bool)value;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return !(bool)value;
}
}
Add it to your App.xaml resource dictionary:
<Application.Resources>
<ResourceDictionary>
<converters:InverseBoolConverter x:Key="InverseBoolConverter" />
</ResourceDictionary>
</Application.Resources>
And apply that to the ViewCell:
<Switch IsToggled="{Binding ShowViewCell, Converter={StaticResource InverseBoolConverter}}" />

How can I add string to binding value of image source?

Hi everyone I'm developing a xamarin app and I have a problem.
I have the next code in xaml:
<ListView x:Name="listName">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Vertical">
<Image Source="{Binding imageName}"></Image>
<Label Text="{Binding name}" TextColor="Black"></Label>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
I need to change the image source property adding a string. For example:
<Image Source="{Binding imageName} + mystring.png"></Image>
<Image Source="{Binding imageName + mystring.png}"></Image>
Can I do this in xaml?
any idea? is possible?
You could use a converter to do this.
public class ImagePostfixValueConverter
: IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var path = value as string;
var postfix = parameter as string;
if (string.IsNullOrEmpty(postfix) || string.IsNullOrEmpty(path))
return value;
return path + postfix;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
Then on your page add:
<ContentPage.Resources>
<ResourceDictionary>
<local:ImagePostfixValueConverter x:Key="PostfixConverter"/>
</ResourceDictionary>
</ContentPage.Resources>
And then in your binding:
<Image Source="{Binding imageName, Converter={StaticResouce PostfixConverter}, ConverterParameter=mystring.png}"></Image>
You could do this in a much simpler way:
<Image Source="{Binding imageName, StringFormat='{0}mystring.png'}"></Image>

Setting foreground of one specific textblockelement in a listbox - wp7

I've got a listbox, which ive bound to an array of strings. The listbox contains a textblock, which has the text of a string in the array. I want to change the foreground of one of those (it may vary which one):
<ListBox x:Name="listBox" ItemsSource="{Binding Options}" ScrollViewer.VerticalScrollBarVisibility="Hidden" Width="400" Height="500" Margin="0,200,0,0" HorizontalAlignment="Center" HorizontalContentAlignment="Center" SelectionChanged="ListBox_SelectionChanged" Loaded="listBox_Loaded">
<ListBox.ItemTemplate>
<DataTemplate>
<ListBoxItem>
<Grid Height="75" Width="400" HorizontalAlignment="Center" >
<TextBlock HorizontalAlignment="Center" Text="{Binding}" Style="{StaticResource SortingOptions}" />
</Grid>
</ListBoxItem>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I just cant seem to get hold of the textblocks, so i can change the foreground on the right one. Does anyone know how i can achieve this? Thanks
Bind the Foreground property to the same value as Text and use a BindingConverter to create a Brush out of it.
E.g.
<Grid.Resources>
<yournamespace:ColorConverter x:Key="colConverter"/>
<Grid.Resources>
<TextBlock
HorizontalAlignment="Center"
Text="{Binding}"
Foreground="{Binding, Converter={StaticResource colConverter}}"
Style="{StaticResource SortingOptions}" />
Add your converter class:
public class ColorConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
// TODO: match from the value parameter to a color.
return new SolidColorBrush(Colors.Red);
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}

Resources