I have Labelrenderer initially it shows single line once i tab readmore, It cannot expanded show single line only in ios. how to achieve this using renderer below screenshot
Xaml
<Label Text="{Binding Comment}" LineBreakMode="{Binding CommentBrkMode}" VerticalTextAlignment="Center" HorizontalTextAlignment="Start">
<Label.GestureRecognizers>
<TapGestureRecognizer Command="{Binding BindingContext.ShowMoreCommand,Source={x:Reference Page}}" CommandParameter="{Binding .}"/>
</Label.GestureRecognizers>
</Label>
<Label Text="{Binding CommentViewText}" IsVisible="{Binding ReadMoreLabelVisible}" Grid.Row="4" Grid.Column="3" TextColor="Blue" HorizontalOptions="EndAndExpand" VerticalOptions="EndAndExpand">
<Label.GestureRecognizers>
<TapGestureRecognizer Command="{Binding BindingContext.ShowMoreCommand,Source={x:Reference Page}}" CommandParameter="{Binding .}"/>
</Label.GestureRecognizers>
</Label>
public class CustomLabelRenderer : LabelRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
{
base.OnElementChanged(e);
if (Control != null)
{
if (Element.LineBreakMode == LineBreakMode.TailTruncation)
{
Control.AdjustsFontSizeToFitWidth = false; //for purists
Control.LineBreakMode = UILineBreakMode.TailTruncation; //the fix
}
}
}
}
Related
On my page there is a 4 expander ,I want to write a code for at a time one expander is expand ,What can I do for this scenario please help me ,For more clarifications I have a add image of expanders ,In this given code there is a one expander show ,but this type of a 4 expander available on my page and i want to expand one at a time
enter image description here
<StackLayout IsVisible="{Binding Synonyms,Converter={x:StaticResource CorrectionTypeVisiableConverter}}" Orientation="Vertical" VerticalOptions="StartAndExpand" HorizontalOptions="FillAndExpand">
<xct:Expander ExpandAnimationEasing="CubicIn"
ExpandAnimationLength="500"
CollapseAnimationEasing="CubicOut"
CollapseAnimationLength="500">
<xct:Expander.Header>
<Frame HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" BorderColor="#F0F0F0" HasShadow="False" >
<StackLayout Orientation="Horizontal" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
<xct:BadgeView Text="{Binding Synonyms,Converter={StaticResource CorrectionCountBadgeConverter}}" BackgroundColor="#FADBD8" BadgePosition="TopLeft" TextColor="#E74C3C" HorizontalOptions="Start" FontSize="16" AutoHide="True" VerticalOptions="CenterAndExpand">
<Label Text=""></Label>
</xct:BadgeView>
<Label Text="{x:Static resources:AppResources.Synonyms}"
FontAttributes="Bold" VerticalOptions="CenterAndExpand"
FontSize="Medium" Style="{StaticResource MenueLableStyle}" HorizontalOptions="StartAndExpand" />
<Image Source="Expand.png"
HorizontalOptions="EndAndExpand"
VerticalOptions="CenterAndExpand">
<Image.Triggers>
<DataTrigger TargetType="Image"
Binding="{Binding Source={RelativeSource AncestorType={x:Type xct:Expander}}, Path=IsExpanded,Mode=OneTime}"
Value="True">
<Setter Property="Source"
Value="collapse.png" />
</DataTrigger>
</Image.Triggers>
</Image>
</StackLayout>
</Frame>
</xct:Expander.Header>
<xct:Expander.ContentTemplate>
<DataTemplate>
<StackLayout BindableLayout.ItemsSource="{Binding Synonyms}" VerticalOptions="StartAndExpand" HorizontalOptions="FillAndExpand">
<BindableLayout.ItemTemplate>
<DataTemplate>
<Frame HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" BorderColor="#F0F0F0" HasShadow="False" >
<Grid >
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<StackLayout Grid.Row="0" Orientation="Horizontal">
<Label Text="{Binding s}" HorizontalOptions="Start" VerticalOptions="Center">
</Label>
<Label Text="--->" HorizontalOptions="Start" VerticalOptions="Center"></Label>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"></ColumnDefinition>
</Grid.ColumnDefinitions>
<xct:BadgeView Grid.Column="0" Text="" BackgroundColor="#FADBD8" BadgePosition="TopRight" TextColor="#E74C3C" FontSize="14" HorizontalOptions="CenterAndExpand" AutoHide="True" VerticalOptions="Center" Background="#FADBD8" WidthRequest="80" HeightRequest="25">
<Label Text="{Binding c}"></Label>
</xct:BadgeView>
<ImageButton Grid.Column="0" Source="Storyedit.png"
HorizontalOptions="EndAndExpand" VerticalOptions="Center" WidthRequest="12" HeightRequest="12"/>
</Grid>
<ImageButton Source="Info.png" Command="{Binding Path=BindingContext.CorrectionInfoCommand,Source={x:Reference Name=storyView}}"
CommandParameter="{Binding .}" HorizontalOptions="EndAndExpand"/>
</StackLayout>
<Button Grid.Row="1" Text="{x:Static resources:AppResources.IgnoreButton}" Style="{StaticResource CancelButton}" VerticalOptions="EndAndExpand" HorizontalOptions="CenterAndExpand" ></Button>
<Button Grid.Row="1" Text="{x:Static resources:AppResources.AcceptButton}" Style="{StaticResource AcceptButton}" VerticalOptions="EndAndExpand" HorizontalOptions="StartAndExpand" ></Button>
<FlexLayout IsVisible="False" Grid.Row="3" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" AlignItems="Start" AlignContent="Center" Direction="Row" Wrap="Wrap" JustifyContent="Center">
<Button Text="{x:Static resources:AppResources.IgnoreButton}" Padding="5" Style="{StaticResource CancelButton}" HorizontalOptions="StartAndExpand"></Button>
<Button Text="{x:Static resources:AppResources.IgnoreAllButton}" Style="{StaticResource CancelButton}" HorizontalOptions="CenterAndExpand" Padding="5"></Button>
<Button Text="{x:Static resources:AppResources.AcceptButton}" Style="{StaticResource AcceptButton}" HorizontalOptions="StartAndExpand" Padding="5"></Button>
<Button Text="{x:Static resources:AppResources.AcceptAllButton}" Style="{StaticResource AcceptButton}" HorizontalOptions="CenterAndExpand" Padding="5"></Button>
</FlexLayout>
</Grid>
</Frame>
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
</DataTemplate>
</xct:Expander.ContentTemplate>
</xct:Expander>
</StackLayout>
You could binding true or false for the IsExpanded property to indicate that the Expander is expanded or collapsed.
I make a simple example for your reference.
Model:
public class Model : INotifyPropertyChanged
{
#region fields
public string _synonyms;
public string _s;
public bool _isexpand;
#endregion
public string Synonyms
{
get { return _synonyms; }
set { _synonyms = value; OnPropertyChanged("Synonyms"); }
}
public string s
{
get { return _s; }
set { _s = value; OnPropertyChanged("s"); }
}
public bool ISexpand
{
get { return _isexpand; }
set { _isexpand = value; OnPropertyChanged("ISexpand"); }
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
ViewModel:
public class ViewModel1
{
public ObservableCollection<Model> models { get; set; }
public ViewModel1()
{
CreateCollection();
}
public void CreateCollection()
{
models = new ObservableCollection<Model>()
{
new Model(){ Synonyms="Synonym1", s="A", ISexpand=false},
new Model(){ Synonyms="Synonym2", s="B",ISexpand=false},
new Model(){ Synonyms="Synonym3", s="C",ISexpand=false},
new Model(){ Synonyms="Synonym4", s="D",ISexpand=false},
new Model(){ Synonyms="Synonym5", s="E",ISexpand=false},
};
}
}
Xaml:
<ContentPage.BindingContext>
<local:ViewModel1></local:ViewModel1>
</ContentPage.BindingContext>
<ContentPage.Content>
<StackLayout x:Name="stacklayout" BindableLayout.ItemsSource="{Binding models}" Orientation="Vertical" VerticalOptions="StartAndExpand" HorizontalOptions="FillAndExpand">
<BindableLayout.ItemTemplate>
<DataTemplate>
<xct:Expander IsExpanded="{Binding ISexpand}" Tapped="Expander_Tapped" >
<xct:Expander.Header>
<Label Text="{Binding Synonyms}"></Label>
</xct:Expander.Header>
<xct:Expander.ContentTemplate>
<DataTemplate>
<Label Text="{Binding s}"></Label>
</DataTemplate>
</xct:Expander.ContentTemplate>
</xct:Expander>
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
</ContentPage.Content>
Code behind:
public partial class Page10 : ContentPage
{
ViewModel1 viewModel1=new ViewModel1();
public Page10()
{
InitializeComponent();
}
int i = 0;
private void Expander_Tapped(object sender, EventArgs e)
{
var expander = sender as Expander;
var label = expander.Header as Label;
var list = viewModel1.models;
foreach (var item in viewModel1.models)
{
if (item.Synonyms == label.Text)
{
item.ISexpand = true;
if (i >= 1)
{
foreach (var item1 in viewModel1.models.ToList())
{
if (item1.Synonyms!= label.Text)
{
item1.ISexpand = false;
}
}
BindableLayout.SetItemsSource(stacklayout, viewModel1.models);
}
}
}
i++;
}
}
OutPut:
https://imgur.com/4D6x1yB
I'm working on mobile app that kinda simulates how to build a Desktop Computer by dragging and dropping an image in order. I work with DropGestureRecognizer with AllowDrop set to True for the Drop Zone Image controls and DragGestureRecognizer with CanDrag set to True for the Drag Image Objects.
The idea is the Drag Image Objects will get dragged and dropped to a Drop Zone Image Control and if they dropped the correct Drag Image, the Drop Zone will accept this as the Image.Source and another Drop Zone will be stacked in front of it to work with the next Desktop Computer component. Otherwise, it would get rejected and the Image.Source will be set to empty or null.
However, i'm encountering a weird issue that, on the first incorrect image dragged, the Image.Source gets reset to empty or null by property but on the actual UI, it doesn't. On the succeeding EventHandler execution, it does get reset. I have a TapGestureRecognizer on the Drop Zone to check if there is an Image.Source set or not.
I'm sorry if my explanation is a bit confusing because English is not my native language and i'm having a hard time explaining it. So please refer to below example in GIF and my code:
View (.xaml):
<ContentPage.Content>
<Grid RowDefinitions="Auto,60,*"
ColumnDefinitions="*">
<RelativeLayout Grid.Row="0" Grid.Column="0" HorizontalOptions="Center">
<Image x:Name="imgCaseDropZone"
RelativeLayout.XConstraint="0"
RelativeLayout.YConstraint="0"
HeightRequest="{Binding ScreenWidth}"
WidthRequest="{Binding ScreenWidth}"
PropertyChanged="CaseDropZone_PropertyChanged"
BackgroundColor="LightGray">
<Image.GestureRecognizers>
<DropGestureRecognizer AllowDrop="True" />
<TapGestureRecognizer Tapped="TapGestureRecognizer_Tapped" />
</Image.GestureRecognizers>
</Image>
</RelativeLayout>
<Label Grid.Row="1" Grid.Column="0"
x:Name="lblDirections"
Text="Directions: Drag the components below in its proper order to the drop zone above."
TextColor="Black"
Padding="10"
VerticalOptions="CenterAndExpand"
HorizontalOptions="CenterAndExpand" />
<ScrollView Grid.Row="2"
Orientation="Horizontal"
Margin="5">
<StackLayout Orientation="Horizontal">
<!--#region Case -->
<Grid RowDefinitions="*,Auto"
IsVisible="{Binding CaseIsVisible}">
<Image Grid.Row="0"
x:Name="imgCaseDragObject"
Source="{Binding CaseImgSource}">
<Image.GestureRecognizers>
<DragGestureRecognizer CanDrag="True" />
</Image.GestureRecognizers>
</Image>
<Label Grid.Row="1"
Text="{Binding CaseLabel}"
TextColor="White"
FontSize="Medium"
BackgroundColor="Gray"
HorizontalTextAlignment="Center" />
</Grid>
<!--#endregion-->
<!--#region Case Cover -->
<Grid RowDefinitions="*,Auto"
IsVisible="{Binding CaseCoverIsVisible}">
<Image Grid.Row="0"
Source="{Binding CaseCoverImgSource}">
<Image.GestureRecognizers>
<DragGestureRecognizer CanDrag="True" />
</Image.GestureRecognizers>
</Image>
<Label Grid.Row="1"
Text="{Binding CaseCoverLabel}"
TextColor="White"
FontSize="Medium"
BackgroundColor="Gray"
HorizontalTextAlignment="Center" />
</Grid>
<!--#endregion-->
<!--#region Case Screw -->
<Grid RowDefinitions="*,Auto"
IsVisible="{Binding CaseScrewIsVisible}">
<Image Grid.Row="0"
Source="{Binding CaseScrewImgSource}">
<Image.GestureRecognizers>
<DragGestureRecognizer CanDrag="True" />
</Image.GestureRecognizers>
</Image>
<Label Grid.Row="1"
Text="{Binding CaseScrewLabel}"
TextColor="White"
FontSize="Medium"
BackgroundColor="Gray"
HorizontalTextAlignment="Center" />
</Grid>
<!--#endregion-->
<!--#region Hard Disk Drive -->
<Grid RowDefinitions="*,Auto"
IsVisible="{Binding HardDiskDriveIsVisible}">
<Image Grid.Row="0"
Source="{Binding HardDiskDriveImgSource}">
<Image.GestureRecognizers>
<DragGestureRecognizer CanDrag="True" />
</Image.GestureRecognizers>
</Image>
<Label Grid.Row="1"
Text="{Binding HardDiskDriveLabel}"
TextColor="White"
FontSize="Medium"
BackgroundColor="Gray"
HorizontalTextAlignment="Center" />
</Grid>
<!--#endregion-->
<!--#region Heatsink -->
<Grid RowDefinitions="*,Auto"
IsVisible="{Binding HeatsinkIsVisible}">
<Image Grid.Row="0"
Source="{Binding HeatsinkImgSource}">
<Image.GestureRecognizers>
<DragGestureRecognizer CanDrag="True" />
</Image.GestureRecognizers>
</Image>
<Label Grid.Row="1"
Text="{Binding HeatsinkLabel}"
TextColor="White"
FontSize="Medium"
BackgroundColor="Gray"
HorizontalTextAlignment="Center" />
</Grid>
<!--#endregion-->
<!--#region Memory Module -->
<Grid RowDefinitions="*,Auto"
IsVisible="{Binding MemoryModuleIsVisible}">
<Image Grid.Row="0"
Source="{Binding MemoryModuleImgSource}">
<Image.GestureRecognizers>
<DragGestureRecognizer CanDrag="True" />
</Image.GestureRecognizers>
</Image>
<Label Grid.Row="1"
Text="{Binding MemoryModuleLabel}"
TextColor="White"
FontSize="Medium"
BackgroundColor="Gray"
HorizontalTextAlignment="Center" />
</Grid>
<!--#endregion-->
<!--#region Motherboard -->
<Grid RowDefinitions="*,Auto"
IsVisible="{Binding MotherboardIsVisible}">
<Image Grid.Row="0"
Source="{Binding MotherboardImgSource}">
<Image.GestureRecognizers>
<DragGestureRecognizer CanDrag="True" />
</Image.GestureRecognizers>
</Image>
<Label Grid.Row="1"
Text="{Binding MotherboardLabel}"
TextColor="White"
FontSize="Medium"
BackgroundColor="Gray"
HorizontalTextAlignment="Center" />
</Grid>
<!--#endregion-->
<!--#region Motherboard Screw -->
<Grid RowDefinitions="*,Auto"
IsVisible="{Binding MotherboardScrewIsVisible}">
<Image Grid.Row="0"
Source="{Binding MotherboardScrewImgSource}">
<Image.GestureRecognizers>
<DragGestureRecognizer CanDrag="True" />
</Image.GestureRecognizers>
</Image>
<Label Grid.Row="1"
Text="{Binding MotherboardScrewLabel}"
TextColor="White"
FontSize="Medium"
BackgroundColor="Gray"
HorizontalTextAlignment="Center" />
</Grid>
<!--#endregion-->
<!--#region Power Supply -->
<Grid RowDefinitions="*,Auto"
IsVisible="{Binding PowerSupplyIsVisible}">
<Image Grid.Row="0"
Source="{Binding PowerSupplyImgSource}">
<Image.GestureRecognizers>
<DragGestureRecognizer CanDrag="True" />
</Image.GestureRecognizers>
</Image>
<Label Grid.Row="1"
Text="{Binding PowerSupplyLabel}"
TextColor="White"
FontSize="Medium"
BackgroundColor="Gray"
HorizontalTextAlignment="Center" />
</Grid>
<!--#endregion-->
<!--#region Processor -->
<Grid RowDefinitions="*,Auto"
IsVisible="{Binding ProcessorIsVisible}">
<Image Grid.Row="0"
Source="{Binding ProcessorImgSource}">
<Image.GestureRecognizers>
<DragGestureRecognizer CanDrag="True" />
</Image.GestureRecognizers>
</Image>
<Label Grid.Row="1"
Text="{Binding ProcessorLabel}"
TextColor="White"
FontSize="Medium"
BackgroundColor="Gray"
HorizontalTextAlignment="Center" />
</Grid>
<!--#endregion-->
</StackLayout>
</ScrollView>
</Grid>
</ContentPage.Content>
View Code (.xaml.cs):
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class AssemblyPage : ContentPage
{
string caseSource;
public AssemblyPage()
{
InitializeComponent();
}
int dragCount = 0;
private void CaseDropZone_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "Source")
{
caseSource = imgCaseDropZone.Source.ToString().Split(':').Last().Trim();
if (string.IsNullOrEmpty(caseSource))
{
return;
}
if (caseSource != "img_assembly_case.png")
{
imgCaseDropZone.Source = string.Empty;
lblDirections.Text = $"Drag Count: {++dragCount}";
}
}
}
private void TapGestureRecognizer_Tapped(object sender, EventArgs e)
{
Application.Current.MainPage.DisplayAlert("", $"{imgCaseDropZone.Source}", "OK");
}
}
ViewModel (.cs):
public class AssemblyViewModel : BaseVM
{
public double ScreenWidth => Xamarin.Forms.Application.Current.MainPage.Width;
#region Case
bool caseIsVisible;
public bool CaseIsVisible
{
get => caseIsVisible;
set => SetProperty(ref caseIsVisible, value);
}
public string CaseImgSource { get; }
public string CaseLabel { get; }
#endregion
#region CaseCover
bool caseCoverIsVisible;
public bool CaseCoverIsVisible
{
get => caseCoverIsVisible;
set => SetProperty(ref caseCoverIsVisible, value);
}
public string CaseCoverImgSource { get; }
public string CaseCoverLabel { get; }
#endregion
#region HardDiskDrive
bool hardDiskDriveIsVisible;
public bool HardDiskDriveIsVisible
{
get => hardDiskDriveIsVisible;
set => SetProperty(ref hardDiskDriveIsVisible, value);
}
public string HardDiskDriveImgSource { get; }
public string HardDiskDriveLabel { get; }
#endregion
#region CaseScrew
bool caseScrewIsVisible;
public bool CaseScrewIsVisible
{
get => caseScrewIsVisible;
set => SetProperty(ref caseScrewIsVisible, value);
}
public string CaseScrewImgSource { get; }
public string CaseScrewLabel { get; }
#endregion
#region Heatsink
bool heatsinkIsVisible;
public bool HeatsinkIsVisible
{
get => heatsinkIsVisible;
set => SetProperty(ref heatsinkIsVisible, value);
}
public string HeatsinkImgSource { get; }
public string HeatsinkLabel { get; }
#endregion
#region MemoryModule
bool memoryModuleIsVisible;
public bool MemoryModuleIsVisible
{
get => memoryModuleIsVisible;
set => SetProperty(ref memoryModuleIsVisible, value);
}
public string MemoryModuleImgSource { get; }
public string MemoryModuleLabel { get; }
#endregion
#region Motherboard
bool motherboardIsVisible;
public bool MotherboardIsVisible
{
get => motherboardIsVisible;
set => SetProperty(ref motherboardIsVisible, value);
}
public string MotherboardImgSource { get; }
public string MotherboardLabel { get; }
#endregion
#region MotherboardScrew
bool motherboardScrewIsVisible;
public bool MotherboardScrewIsVisible
{
get => motherboardScrewIsVisible;
set => SetProperty(ref motherboardScrewIsVisible, value);
}
public string MotherboardScrewImgSource { get; }
public string MotherboardScrewLabel { get; }
#endregion
#region PowerSupply
bool powerSupplyIsVisible;
public bool PowerSupplyIsVisible
{
get => powerSupplyIsVisible;
set => SetProperty(ref powerSupplyIsVisible, value);
}
public string PowerSupplyImgSource { get; }
public string PowerSupplyLabel { get; }
#endregion
#region Processor
bool processorIsVisible;
public bool ProcessorIsVisible
{
get => processorIsVisible;
set => SetProperty(ref processorIsVisible, value);
}
public string ProcessorImgSource { get; }
public string ProcessorLabel { get; }
#endregion
public AssemblyViewModel()
{
CaseIsVisible = true;
CaseImgSource = "img_assembly_case.png";
CaseLabel = "Case";
CaseCoverIsVisible = true;
CaseCoverImgSource = "img_assembly_case_cover.png";
CaseCoverLabel = "Case Cover";
CaseScrewIsVisible = true;
CaseScrewImgSource = "img_assembly_case_screw.png";
CaseScrewLabel = "Case Screw";
HardDiskDriveIsVisible = true;
HardDiskDriveImgSource = "img_assembly_hard_disk_drive.png";
HardDiskDriveLabel = "Hard Disk Drive";
HeatsinkIsVisible = true;
HeatsinkImgSource = "img_assembly_heat_sink.png";
HeatsinkLabel = "Heatsink";
MemoryModuleIsVisible = true;
MemoryModuleImgSource = "img_assembly_memory_module.png";
MemoryModuleLabel = "Memory Module";
MotherboardIsVisible = true;
MotherboardImgSource = "img_assembly_motherboard.png";
MotherboardLabel = "Motherboard";
MotherboardScrewIsVisible = true;
MotherboardScrewImgSource = "img_assembly_motherboard_screw.png";
MotherboardScrewLabel = "Motherboard Screw";
PowerSupplyIsVisible = true;
PowerSupplyImgSource = "img_assembly_power_supply.png";
PowerSupplyLabel = "Power Supply";
ProcessorIsVisible = true;
ProcessorImgSource = "img_assembly_processor.png";
ProcessorLabel = "Processor";
}
}
Current Build demo in GIF: https://imgur.com/a/oLeM9DV (i can't directly link the GIF because its too big)
Because when you trigger the PropertyChanged event, the drag and drop action has already been completed and the image has been automatically set to the target.
We could make that judgment as soon as we drag it over the target with DragOver event.Then make an action when the drag and drop is complete with Drop event.
For example,change the codes of the Image (imgCaseDropZone):
<Image x:Name="imgCaseDropZone"
RelativeLayout.XConstraint="0"
RelativeLayout.YConstraint="0"
RelativeLayout.WidthConstraint="400"
RelativeLayout.HeightConstraint="400"
BackgroundColor="LightGray"
>
<Image.GestureRecognizers>
<DropGestureRecognizer AllowDrop="{Binding CaseIsVisible}" DragOver="CaseDropZone_DragOver" Drop="CaseDropZone_Drop"/>
<TapGestureRecognizer Tapped="TapGestureRecognizer_Tapped" />
</Image.GestureRecognizers>
</Image>
in the code behind:
private void CaseDropZone_DragOver(object sender, DragEventArgs e)
{
FileImageSource file = (FileImageSource)e.Data.Image;
string name = file.File;
if (name != "img_assembly_case.png")
{
e.Data.Image = string.Empty; // set the value string.Empty when drag it over the target,then it will fill the empty source to the image.
}
}
private async void CaseDropZone_Drop(object sender, DropEventArgs e)
{
var ctx = (BindingContext as AssemblyViewModel);
FileImageSource source = (FileImageSource)await e.Data.GetImageAsync();
string name = source.File;
if (name == "img_assembly_case.png")
{
ctx.CaseIsVisible = false;
imgMotherboardDropZone.IsVisible = true;
}
else
{
Global.Score.PCAssembly -= 5;
DisplayAlert($"Score: {Global.Score.PCAssembly}", "The pre-requisite component for this part has not yet been placed.", "OK");
}
}
Other Images are modified like this.
I'm new to Xamarin and I would like to know how can I set the DatePicker to be an image for example a calender instead of being text with a line under it (default).
The goal is to have an entry and next to it a calender image to have it's behaviour like a DatePicker like in the image below:
I have the following code but i have DatePicker commented. I tried to set isVisible = 'false' and have the image on it's position but it didn't work.
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="360" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Frame Style="{StaticResource FrameStyle}">
<controls:CustomEntry x:Name="DataDocEntry" Grid.Column="0" Text="{Binding Date, StringFormat='{0:d/M/yy}', Source={x:Reference MainDatePicker}}" IsEnabled="false" Style="{StaticResource EntryStyle}" />
</Frame>
<!--<DatePicker x:Name="MainDatePicker" Grid.Column="1" MinimumDate="1/1/2018" MaximumDate="12/31/2030" HeightRequest="30" />-->
<Image VerticalOptions="Center" Grid.Column="1" HorizontalOptions="End" Source="icalendar.png" HeightRequest="30" WidthRequest="30">
<Image.GestureRecognizers>
<TapGestureRecognizer Tapped="Calendario_Clicked" NumberOfTapsRequired="1" />
</Image.GestureRecognizers>
</Image>
</Grid>
I also created a DatePickerRenderer to customize the DatePicker to try to set it's background as image but wasn't sucessful either.
DatePickerRenderer.cs
using Android.Content;
using FormsApp.Droid;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
[assembly: ExportRenderer(typeof(DatePicker), typeof(MyRenderer))]
namespace FormsApp.Droid
{
class MyRenderer : DatePickerRenderer
{
public MyRenderer(Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<DatePicker> e)
{
base.OnElementChanged(e);
if (Control != null)
{
//Control.Background = "icalendar.png";
}
}
}
}
Best regards
You could hide the DataPicker and use the Focus in the click event of image.
xaml:
<StackLayout Orientation="Horizontal" VerticalOptions="StartAndExpand">
<Entry x:Name="entry" />
<Image
HeightRequest="20"
HorizontalOptions="EndAndExpand"
Source="calendar.png"
WidthRequest="20">
<Image.GestureRecognizers>
<TapGestureRecognizer Tapped="TapGestureRecognizer_Tapped" />
</Image.GestureRecognizers>
</Image>
<DatePicker
x:Name="dataPicker"
IsVisible="false"
Unfocused="dataPicker_Unfocused" />
</StackLayout>
Code behind:
private void dataPicker_Unfocused(object sender, FocusEventArgs e)
{
entry.Text =dataPicker.Date.ToString();
}
private void TapGestureRecognizer_Tapped(object sender, EventArgs e)
{
dataPicker.Focus();
}
hello i want to pass the Label with the button in xaml
its a list view and each row has her own Label and i want update each row by the label
<Label Grid.Column="2"
Grid.Row="1"
Text="{Binding Label}"
FontSize="20"
TextColor="Black"
Margin="0,10,0,0"
FontFamily="{StaticResource font}"
HorizontalOptions="Start"
VerticalOptions="Center"/>
<ImageButton Grid.Column="2"
Grid.Row="0"
HorizontalOptions="End"
VerticalOptions="End"
Source="plus.png"
Margin="9"
clicked ="update"
BackgroundColor="Transparent"/>
and the function in the class
public void update (object sender , EventArgs e)
{
update by the Label
}
i know that's there is something with commands but i'm beginner and i don't know how to use it i tried this and i didn't work.
Command="{Binding Path=BindingContext.UpdateCommand, Source={x:Reference Name=listViewEvent}}"
CommandParameter="{Binding Label}"
and the function is this
UpdateCommand = new Command<string>(async (args) => {
String Label = args as string;
DisplayAlert("update", "update", "OK");
_ = Navigation.PushAsync(new AddReminder(Label));
});
and the alert didn't show
please i need help
you don't need to "pass" the Label
<ImageButton Grid.Column="2" Cilcked="update" ... />
protected void update(object sender, EventArgs a)
{
var btn = (ImageButton)sender;
// MyClassName should be the name of your model class
// this will get you the object referenced by the selected row
var item = (MyClassName)btn.BindingContext;
// then you can reference any property of item
// ie, item.Label, etc
}
<Label x:Name="myLabel"
Grid.Column="2"
Grid.Row="1"
Text="{Binding Label}"
FontSize="20"
TextColor="Black"
Margin="0,10,0,0"
FontFamily="{StaticResource font}"
HorizontalOptions="Start"
VerticalOptions="Center"/>
<ImageButton Grid.Column="2"
Grid.Row="0"
HorizontalOptions="End"
VerticalOptions="End"
Source="plus.png"
Margin="9"
clicked ="update"
BackgroundColor="Transparent"
CommandParameter={x:Reference myLabel}/>
And then in code behind you can get the label
protected void update(object sender, EventArgs a)
{
var btn = (ImageButton)sender;
var label = btn.CommandParameter as Xamarin.Forms.Label;
}
I want to display a ListView and other controls inside a ScrollView. All is bound to a ViewModel. My attempts failed because it's not recommend to put a ListView inside a ScrollView. As I use a complex ViewCell DataTemplate, I did not consider to add my items in the code behind file as Buttons instead of a ListView.
Hope someone can show me a Xaml or CS pattern to achieve my goal.
Please only suggest a solution which works on iOS and Android!
Thanks
Eric
This is XAML code
<ScrollView Padding="2">
<StackLayout HorizontalOptions="FillAndExpand">
<Grid HorizontalOptions="FillAndExpand">
<StackLayout>
<ScrollView Orientation="Horizontal">
<ListView BackgroundColor="Transparent" ItemsSource="{Binding UsersList}" SeparatorVisibility="None" x:Name="YourListView" RowHeight="50">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout BackgroundColor="Transparent" Padding="5">
<Button Text="{Binding UserName}" WidthRequest="115" HorizontalOptions="FillAndExpand" TextColor="White" BackgroundColor="#4b76c4" FontAttributes="Bold" FontSize="20" FontFamily="Avenir Book"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ScrollView>
</StackLayout>
</Grid>
</StackLayout>
</ScrollView>
and .cs file you need set BindingContext
BindingContext = new YourViewModel();
Solution:
As Rodrigo E suggested I download the latest Xamarin Evolve App 2016. After digging through the code I adjusted/simplified the FeedPage.xaml in the solution to that:
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:XamarinEvolve.Clients.UI;assembly=XamarinEvolve.Clients.UI"
xmlns:pull="clr-namespace:Refractored.XamForms.PullToRefresh;assembly=Refractored.XamForms.PullToRefresh"
x:Class="XamarinEvolve.Clients.UI.FeedPage"
x:Name="FeedPage"
Title="Evolve Feed"
Icon="tab_feed.png"
BackgroundColor="{DynamicResource WindowBackgroundTable}">
<pull:PullToRefreshLayout
IsPullToRefreshEnabled="True"
RefreshCommand="{Binding RefreshCommand}"
IsRefreshing="{Binding IsBusy}">
<local:AlwaysScrollView
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand">
<StackLayout>
<StackLayout Spacing="0">
<local:NonScrollableListView
x:Name="ListViewSessions"
ItemsSource="{Binding Sessions}">
<local:NonScrollableListView.RowHeight>
<OnPlatform x:TypeArguments="x:Int32" Android="50" iOS="50" WinPhone="50"/>
</local:NonScrollableListView.RowHeight>
<local:NonScrollableListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Button Text="{Binding Title}" BackgroundColor="Black" TextColor="Green" />
</ViewCell>
</DataTemplate>
</local:NonScrollableListView.ItemTemplate>
</local:NonScrollableListView>
</StackLayout>
<StackLayout Padding="0" Spacing="0" BackgroundColor="Green">
<Button Text="OTHER" BackgroundColor="Blue" TextColor="White" />
<Button Text="OTHER" BackgroundColor="Blue" TextColor="White" />
<Button Text="OTHER" BackgroundColor="Blue" TextColor="White" />
<Button Text="OTHER" BackgroundColor="Blue" TextColor="White" />
<Button Text="OTHER" BackgroundColor="Blue" TextColor="White" />
<Button Text="OTHER" BackgroundColor="Blue" TextColor="White" />
</StackLayout>
</StackLayout>
</local:AlwaysScrollView>
</pull:PullToRefreshLayout>
There are a few things to do:
In the FeedViewModel.cs I added that code for a quick test:
async Task ExecuteLoadSessionsCommandAsync()
{
if (LoadingSessions)
return;
LoadingSessions = true;
try
{
NoSessions = false;
Sessions.Clear();
OnPropertyChanged("Sessions");
#if DEBUG
await Task.Delay(1000);
#endif
var sessions = await StoreManager.SessionStore.GetNextSessions();
var testSessions = new List<Session>();
testSessions.Add(new Session
{
Title = "TEST"
});
testSessions.Add(new Session
{
Title = "TEST"
});
testSessions.Add(new Session
{
Title = "TEST"
});
sessions = testSessions;
if(sessions != null)
Sessions.AddRange(sessions);
NoSessions = Sessions.Count == 0;
}
catch(Exception ex)
{
ex.Data["method"] = "ExecuteLoadSessionsCommandAsync";
Logger.Report(ex);
NoSessions = true;
}
finally
{
LoadingSessions = false;
}
}
You have to reference the package Refractored.XamForms.PullToRefresh to get the Pull-to-Refresh behavor.
This is in that namespace referenced: xmlns:pull="clr-namespace:Refractored.XamForms.PullToRefresh;assembly=Refractored.XamForms.PullToRefresh"
You have to Copy the AlwaysScrollView , NonScrollableListView to your PCL library.
refercene it with: xmlns:local="clr-namespace:"
In your iOS Project add that custom ListView Renderer:
public class NonScrollableListViewRenderer : ListViewRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs e)
{
base.OnElementChanged(e);
if (Control != null)
Control.ScrollEnabled = false;
}
}
public class AlwaysScrollViewRenderer : ScrollViewRenderer
{
public static void Initialize()
{
var test = DateTime.UtcNow;
}
protected override void OnElementChanged(VisualElementChangedEventArgs e)
{
base.OnElementChanged(e);
this.AlwaysBounceVertical = true;
}
}
See file: Renderer
Put that CollectionChanged Handler in your Code-behind file:
ViewModel.Sessions.CollectionChanged += (sender, e) =>
{
var adjust = Device.OS != TargetPlatform.Android ? 1 : -ViewModel.Sessions.Count + 1;
ListViewSessions.HeightRequest = (ViewModel.Sessions.Count * ListViewSessions.RowHeight) - adjust;
};
See File FeedPage.cs.xaml: FeedPage.cs.xaml