Related
I'm trying to create a ListView Page that works for every object in my app where I can show all the objects received by parameter from a List<object> where I don't know which object the page will have to handle, I also receive the fields to show as parameters in a List <string, string> where the first string is the type of the field (header/subheader/image) and for that, I had to use XAML Reader so I could create the data bindings in the code behind.
Here's my code:
protected override void OnNavigatedTo(NavigationEventArgs e)
{
var param = (Dictionary<string, object>)e.Parameter;
_ItemsList = (List<object>)param["itemsList"];
_Fields = (Dictionary<string, string>)param["fields"];
_DetailsPage = (Type)param["detailPage"];
EditCommand = new UniversalListViewCommand();
ObjListView.ItemsSource = UniversalAutoSuggestBox.ItemsSource = _ItemsList;
MainStackPanel.DataContext = this;
ObjListView.ItemTemplate = NormalItemTemplate = (DataTemplate)XamlReader.Load(GenerateDataTemplate("NormalItemTemplate"));
SelectedItemTemplate = (DataTemplate)XamlReader.Load(GenerateDataTemplate("SelectedItemTemplate"));
}
public string GenerateDataTemplate(string param)
{
StringBuilder sbTemp = new();
//Data Template definition
if (param == "NormalItemTemplate") sbTemp.Append("<DataTemplate x:Key=\"NormalItemTemplate\" ");
if (param == "SelectedItemTemplate") sbTemp.Append("<DataTemplate x:Key=\"SelectedItemTemplate\" ");
//sbTemp.Append("x:Class = \"xizPrototipo_0_2.Pages.UniversalListViewPage\" ");
sbTemp.Append(#"xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation"" ");
sbTemp.Append(#"xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"">");
//Grid definition
sbTemp.Append("<Grid MinWidth=\"350\" Margin=\"5\">");
//Grid row definition
sbTemp.Append("<Grid.RowDefinitions>");
sbTemp.Append("<RowDefinition Height = \"*\" />");
sbTemp.Append("<RowDefinition Height = \"*\" />");
sbTemp.Append("<RowDefinition Height = \"*\" />");
sbTemp.Append("</Grid.RowDefinitions>");
//Grid column definition
sbTemp.Append("<Grid.ColumnDefinitions>");
sbTemp.Append("<ColumnDefinition Width = \"Auto\"/>");
sbTemp.Append("<ColumnDefinition Width = \"*\" />");
sbTemp.Append("</Grid.ColumnDefinitions>");
//Ellipse definition
sbTemp.Append("<Ellipse Grid.Row=\"0\" Grid.RowSpan=\"2\" Width = \"32\" Height = \"32\" Margin = \"6\" VerticalAlignment = \"Center\" HorizontalAlignment = \"Center\">");
sbTemp.Append("<Ellipse.Fill> <ImageBrush x:Name =\"LogoImage\" ImageSource = \"{Binding " + _Fields["Image"] + "}\" /> </Ellipse.Fill> ");
sbTemp.Append("</Ellipse>");
//Header Text Block Definition
sbTemp.Append("<TextBlock Grid.Row = \"0\" Grid.Column = \"1\" Text = \"{Binding " + _Fields["Header"] + "}\" Style = \"{ThemeResource BaseTextBlockStyle}\" Margin = \"12,6,0,0\"/> ");
//Subheader Text Block Definition
sbTemp.Append("<TextBlock Grid.Row=\"1\" Grid.Column = \"1\" Text = \"{Binding " + _Fields["Subheader"] + "}\" Style = \"{ThemeResource BodyTextBlockStyle}\" Margin = \"12,0,0,6\" /> ");
//Button (case Selected)
if (param == "SelectedItemTemplate")
{
sbTemp.Append("<StackPanel Grid.Row=\"2\" Grid.Column=\"1\" Orientation =\"Horizontal\" HorizontalAlignment =\"Right\" Spacing = \"5\" > ");
sbTemp.Append("<Button x:Name=\"EditButton\" Content=\"Editar\" Click=\"AlterButton_Click\" />");
sbTemp.Append("</StackPanel>");
}
//Grid end
sbTemp.Append("</Grid>");
//DataTemplate end
sbTemp.Append("</DataTemplate>");
return sbTemp.ToString();
}
With this method I could get the outcome that I wanted but when I click the button created in the following line it don't fires any event:
sbTemp.Append("<Button x:Name=\"EditButton\" Content=\"Editar\" Click=\"AlterButton_Click\" />");
I also tried using commands, Data Template selector and still I couldn't do anything with that button.
Does anyone know how can I put that button to work?
(Yes, I have the event on the button created and a function to change the Data Template to show the button.)
Data Template Button created in XamlReader don't firing events
I am afraid it will not respond to the click event handler created from the string xaml. Because the click event registration process will be saved in the xxpage.g.cs file during pre-compilation. However, if you load the data template from the string runtime. It will not register for this event.
So the better way is binding command for button.
For example
public MainPage()
{
this.InitializeComponent();
DataTemplate itmeTemplate = (DataTemplate)XamlReader.Load(
#"<DataTemplate xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'>
<Button Command='{Binding BtnClickCommand}' Content='Editor' />
</DataTemplate>");
TestListView.ItemTemplate = itmeTemplate;
NumbersList = new ObservableCollection<Item>();
for (int i = 0; i < 50; i++)
{
var item = new Item ();
NumbersList.Add(item);
}
TestListView.ItemsSource = NumbersList;
}
public ObservableCollection<Item> NumbersList { get; set; }
Model
public class Item : INotifyPropertyChanged
{
public ICommand BtnClickCommand
{
get
{
return new RelayCommand(() =>
{
});
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
// Raise the PropertyChanged event, passing the name of the property whose value has changed.
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
Xaml Code
<Grid x:Name="RootGrid">
<ListView
x:Name="TestListView"
ItemsSource="{x:Bind NumbersList}"
Visibility="Visible">
</ListView>
</Grid>
Update 1
public MainPage()
{
this.InitializeComponent();
this.DataContext = this;
DataTemplate itmeTemplate = (DataTemplate)XamlReader.Load(
#"<DataTemplate xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'>
<Button Command='{Binding DataContext.BtnClickCommand, ElementName=TestListView}' Content='Editor' />
</DataTemplate>");
TestListView.ItemTemplate = itmeTemplate;
NumbersList = new ObservableCollection<Item>();
for (int i = 0; i < 50; i++)
{
var item = new Item ();
NumbersList.Add(item);
}
TestListView.ItemsSource = NumbersList;
}
public ICommand BtnClickCommand
{
get
{
return new RelayCommand(async () =>
{
});
}
}
I have made my point cloud using the code from the librealsense:
var points = pc.Process(depthFrame).As<Points>();
//float depth = depthFrame.GetDistance(x, y);
//bbox = (287, 23, 86, 320);
// We colorize the depth frame for visualization purposes
var colorizedDepth = colorizer.Process<VideoFrame>(depthFrame).DisposeWith(frames);
//var org = Cv2.ImRead(colorFrame);
// CopyVertices is extensible, any of these will do:
//var vertices = new float[points.Count * 3];
var vertices = new Intel.RealSense.Math.Vertex[points.Count];
// var vertices = new UnityEngine.Vector3[points.Count];
// var vertices = new System.Numerics.Vector3[points.Count]; // SIMD
// var vertices = new GlmSharp.vec3[points.Count];
//var vertices = new byte[points.Count * 3 * sizeof(float)];
points.CopyVertices(vertices);
And I have converted the point cloud to a Point3DCollection from Media3D:
Point3DCollection pointss = new Point3DCollection();
foreach (var vertex in vertices)
{
var point3D = new Point3D(vertex.x, vertex.y, vertex.z);
pointss.Add(point3D);
}
I want to display those points using this line in the XAML file:
<h:HelixViewport3D Grid.ColumnSpan="1" Grid.Column="1" Margin="2.4,1,0,-0.4" >
<h:DefaultLights/>
<h:PointsVisual3D Points="{Binding pointss}" Color="Red" Size ="2"/>
</h:HelixViewport3D>
But I don't see my point cloud. Is there something wrong with my code?
The code that I am using right now looks like this. I have added what was given in the answer But I get the error object reference is not set on an example of an object. The code I am using is below:
namespace Intel.RealSense
{
/// <summary>
/// Interaction logic for Window.xaml
/// </summary>
public partial class CaptureWindow : System.Windows.Window
{
private Pipeline pipeline;
private Colorizer colorizer;
private CancellationTokenSource tokenSource = new CancellationTokenSource();
private Pipeline pipe = new Pipeline();
private PointCloud pc = new PointCloud();
private ThresholdFilter threshold;
private Point3DCollection _pointss;
public Point3DCollection pointss
{
get => _pointss;
set
{
if (_pointss == value)
return;
_pointss = value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
//static CvTrackbar Track;
//static OpenCvSharp.Point[][] contours;
//static HierarchyIndex[] hierarchy;
static Action<VideoFrame> UpdateImage(Image img)
{
var wbmp = img.Source as WriteableBitmap;
return new Action<VideoFrame>(frame =>
{
var rect = new Int32Rect(0, 0, frame.Width, frame.Height);
wbmp.WritePixels(rect, frame.Data, frame.Stride * frame.Height, frame.Stride);
});
}
public CaptureWindow()
{
InitializeComponent();
ModelImporter import = new ModelImporter();
try
{
Action<VideoFrame> updateDepth;
Action<VideoFrame> updateColor;
// The colorizer processing block will be used to visualize the depth frames.
colorizer = new Colorizer();
// Create and config the pipeline to strem color and depth frames.
pipeline = new Pipeline();
var cfg = new Config();
cfg.EnableStream(Stream.Depth, 640, 480);
cfg.EnableStream(Stream.Color, Format.Rgb8);
var pp = pipeline.Start(cfg);
PipelineProfile selection = pp;
var depth_stream = selection.GetStream<VideoStreamProfile>(Stream.Depth);
Intrinsics i = depth_stream.GetIntrinsics();
float[] fov = i.FOV;
SetupWindow(pp, out updateDepth, out updateColor);
Task.Factory.StartNew(() =>
{
while (!tokenSource.Token.IsCancellationRequested)
{
threshold = new ThresholdFilter();
threshold.Options[Option.MinDistance].Value = 0.0F;
threshold.Options[Option.MaxDistance].Value = 0.1F;
using (var releaser = new FramesReleaser())
{
using (var frames = pipeline.WaitForFrames().DisposeWith(releaser))
{
var pframes = frames
.ApplyFilter(threshold).DisposeWith(releaser);
}
}
// We wait for the next available FrameSet and using it as a releaser object that would track
// all newly allocated .NET frames, and ensure deterministic finalization
// at the end of scope.
using (var frames = pipeline.WaitForFrames())
{
var colorFrame = frames.ColorFrame.DisposeWith(frames);
var depthFrame = frames.DepthFrame.DisposeWith(frames);
var points = pc.Process(depthFrame).As<Points>();
//float depth = depthFrame.GetDistance(x, y);
//bbox = (287, 23, 86, 320);
// We colorize the depth frame for visualization purposes
var colorizedDepth = colorizer.Process<VideoFrame>(depthFrame).DisposeWith(frames);
//var org = Cv2.ImRead(colorFrame);
// CopyVertices is extensible, any of these will do:
//var vertices = new float[points.Count * 3];
var vertices = new Intel.RealSense.Math.Vertex[points.Count];
// var vertices = new UnityEngine.Vector3[points.Count];
// var vertices = new System.Numerics.Vector3[points.Count]; // SIMD
// var vertices = new GlmSharp.vec3[points.Count];
//var vertices = new byte[points.Count * 3 * sizeof(float)];
points.CopyVertices(vertices);
//Point3DCollection pointss = new Point3DCollection();
foreach (var vertex in vertices)
{
var point3D = new Point3D(vertex.x, vertex.y, vertex.z);
pointss.Add(point3D);
}
// Render the frames.
Dispatcher.Invoke(DispatcherPriority.Render, updateDepth, colorizedDepth);
Dispatcher.Invoke(DispatcherPriority.Render, updateColor, colorFrame);
Dispatcher.Invoke(new Action(() =>
{
String depth_dev_sn = depthFrame.Sensor.Info[CameraInfo.SerialNumber];
txtTimeStamp.Text = depth_dev_sn + " : " + String.Format("{0,-20:0.00}", depthFrame.Timestamp) + "(" + depthFrame.TimestampDomain.ToString() + ")";
}));
//HelixToolkit.Wpf.
}
}
}, tokenSource.Token);
}
catch (Exception ex)
{
System.Windows.MessageBox.Show(ex.Message);
System.Windows.Application.Current.Shutdown();
}
}
private void control_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
tokenSource.Cancel();
}
private void SetupWindow(PipelineProfile pipelineProfile, out Action<VideoFrame> depth, out Action<VideoFrame> color)
{
using (var p = pipelineProfile.GetStream(Stream.Depth).As<VideoStreamProfile>())
imgDepth.Source = new WriteableBitmap(p.Width, p.Height, 96d, 96d, PixelFormats.Rgb24, null);
depth = UpdateImage(imgDepth);
using (var p = pipelineProfile.GetStream(Stream.Color).As<VideoStreamProfile>())
imgColor.Source = new WriteableBitmap(p.Width, p.Height, 96d, 96d, PixelFormats.Rgb24, null);
color = UpdateImage(imgColor);
}
}
You can only bind to public properties, not to fields, so you have to define it like this:
public Point3DCollection pointss { get; } = new Point3DCollection();
If you want to reassign the collection at runtime, you should also implement INotifyPropertyChanged, otherwise assigning a new collection will not trigger a binding update and the change will not be reflected in the UI.
public class YourViewModel : INotifyPropertyChanged
{
private Point3DCollection _pointss;
public Point3DCollection pointss
{
get => _pointss;
set
{
if (_points == value)
return;
_points = value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
when I play a video with video, it presents black bands in the top and bottom part of the video, like in image in the URL
https://imgur.com/a/JiUv8rt. I'd like to remove the bands and display just the video in an absolute layout. how can I reach my goal?
<pages:PopupPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:pages="clr-namespace:Rg.Plugins.Popup.Pages;assembly=Rg.Plugins.Popup"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
xmlns:animations="clr-namespace:Rg.Plugins.Popup.Animations;assembly=Rg.Plugins.Popup"
xmlns:shared="clr-namespace:LibVLCSharp.Forms.Shared;assembly=LibVLCSharp.Forms"
x:Class="App.Pages.WebcamVideoPopUpPage"
BackgroundColor="Transparent">
<pages:PopupPage.Animation>
<animations:ScaleAnimation
PositionIn="Center"
PositionOut="Center"
ScaleIn="1.2"
ScaleOut="0.8"
DurationIn="400"
DurationOut="300"
EasingIn="SinOut"
EasingOut="SinIn"
HasBackgroundAnimation="True"/>
</pages:PopupPage.Animation>
<AbsoluteLayout x:Name="AbsoluteLayoutWebcam"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand">
<shared:VideoView x:Name="VideoViewWebcam"
AbsoluteLayout.LayoutFlags="All"
AbsoluteLayout.LayoutBounds="0, 0, 1, 1"
MediaPlayer ="{Binding MediaPlayer}"
MediaPlayerChanged ="VideoView_MediaPlayerChanged"/>
<Label x:Name="DescriptionWebcam"
AbsoluteLayout.LayoutFlags="All"
AbsoluteLayout.LayoutBounds="0, 0, 1, .2"
HorizontalOptions="Fill"
VerticalOptions="Fill"
Text="{Binding InfoWebcam}"
FontSize="Large"
TextColor="White"/>
</AbsoluteLayout>
</pages:PopupPage>
UPDATE
I update at latest pre-release as #mtz suggested me, and I modified my code in the following way:
public partial class WebcamVideoPopUpPage : PopupPage
{
public WebcamVideoPopUpPage()
{
var vm = App.Locator.WebCamVideoVM;
this.BindingContext = vm;
InitializeComponent();
MediaPlayerWebcam.VideoView.MediaPlayerChanged += VideoView_MediaPlayerChanged;
MediaPlayerWebcam.MediaPlayer.AspectRatio = "FitScreen";
}
protected override void OnAppearing()
{
base.OnAppearing();
Messenger.Default.Send(new OnApperingVideoMessage());
}
private void VideoView_MediaPlayerChanged(object sender, LibVLCSharp.Shared.MediaPlayerChangedEventArgs e)
{
Messenger.Default.Send(new OnVideoViewInitializedMessage());
}
protected override void OnDisappearing()
{
base.OnDisappearing();
MediaPlayerWebcam.MediaPlayer.Stop();
MediaPlayerWebcam.MediaPlayer = null;
}
}
My xaml:
<AbsoluteLayout x:Name="AbsoluteLayoutWebcam"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand">
<shared:MediaPlayerElement x:Name="MediaPlayerWebcam"
AbsoluteLayout.LayoutFlags="All"
AbsoluteLayout.LayoutBounds="0, 0, 1, .4"
MediaPlayer ="{Binding MediaPlayer}"/>
<Label x:Name="DescriptionWebcam"
AbsoluteLayout.LayoutFlags="All"
AbsoluteLayout.LayoutBounds="0, 0, 1, .2"
HorizontalOptions="Fill"
VerticalOptions="Fill"
Text="{Binding InfoWebcam}"
FontSize="Large"
TextColor="White"/>
</AbsoluteLayout>
My viewModel:
public class WebcamVideoViewModel : BaseViewModel
{
private LibVLC LibVLC { get; set; }
private bool IsLoaded { get; set; }
private bool IsVideoViewInitialized { get; set; }
private Media Media { get; set; }
private MediaPlayer _mediaPlayer;
public MediaPlayer MediaPlayer
{
get { return _mediaPlayer; }
set
{
_mediaPlayer = value;
OnPropertyChanged();
}
}
private string _InfoWebcam { get; set; }
public string InfoWebcam
{
get { return _InfoWebcam; }
set
{
_InfoWebcam = value;
OnPropertyChanged();
}
}
public WebcamVideoViewModel(INavigationService navigationService, IApiAutostradeManagerFactory apiAutostradeFactory) : base(navigationService, apiAutostradeFactory)
{
Messenger.Default.Register<InfoWebcamVideoMessage>(this, OnReceivedInfoWebcam);
Messenger.Default.Register<OnApperingVideoMessage>(this, OnAppearing);
Messenger.Default.Register<OnVideoViewInitializedMessage>(this, OnVideoViewInitialized);
Task.Run(Initialize);
}
private void Initialize()
{
Core.Initialize();
LibVLC = new LibVLC();
MediaPlayer = new MediaPlayer(LibVLC);
}
private async void OnReceivedInfoWebcam(InfoWebcamVideoMessage msg)
{
var response = await ApiManager.GetVideoWebcam(msg.Mpr, msg.Uuid);
if (response.IsSuccessStatusCode)
{
InfoWebcam = msg.T_Description_webcam;
var stream = await response.Content.ReadAsStreamAsync();
Media = new Media(LibVLC, stream);
Play();
}
}
public void OnAppearing(OnApperingVideoMessage msg)
{
IsLoaded = true;
}
public void OnVideoViewInitialized(OnVideoViewInitializedMessage msg)
{
IsVideoViewInitialized = true;
}
private void Play()
{
if (IsLoaded && IsVideoViewInitialized)
{
MediaPlayer.Play(Media);
}
}
}
Now i'm closer to solution because videoView is resizable with the button present at bootm, but I'd like to get at start the fill AspectRatio and I don't want anything expect the video(In other words, I'd want to remove seek bar and resize video button). Another problem is that after I close mediaPlayer, and I open again a new video, my app crashes. Any advice?
You need to change the aspect ratio to "fill the screen".
See how to here: https://github.com/videolan/libvlcsharp/blob/91b8f06ee1bedd9b3219a4e9ade0a9c44f59fda8/LibVLCSharp.Forms/Shared/PlaybackControls.xaml.cs#L926 or use the latest pre-release LibVLCSharp.Forms package that contains the MediaPlayerElement which has this feature built-in (soon in stable version).
What you just trying is to stretch the video. But remember it will effect video quality.
To remain simple, you can try this working and tested code:
MediaPlayerWebcam.MediaPlayer.AspectRatio = $"{MediaPlayerWebcam.Width.ToString()}:{MediaPlayerWebcam.Height.ToString()}";
MediaPlayerWebcam.Scale = 0;
My scenario is a fullscreen player, I do it with these codes refer to LibVLCSharp.Forms, hope it will be helpful. the code deal with fullscreen(commented) or fill screen with video.
public void PlayerFullScreen()
{
//restore
if (_isFullScreen)
{
RestoreDefaultWindowInfo();
_isFullScreen = false;
_mediaPlayer.Scale = _originalScale; //reset
_mediaPlayer.AspectRatio = _originalAspectRatio;
//Mouse.Capture(null);
playerBar.Visibility = Visibility.Visible;
}
else // fullscreen(stretch video)
{
this.WindowStyle = WindowStyle.None;
this.ResizeMode = ResizeMode.NoResize;
this.Left = 0;
this.Top = 0;
this.Width = SystemParameters.VirtualScreenWidth;
this.Height = SystemParameters.VirtualScreenHeight;
//this.Topmost = true;
_isFullScreen = true;
_originalScale = _mediaPlayer.Scale; // save original
_originalAspectRatio = _mediaPlayer.AspectRatio;
playerBar.Visibility = Visibility.Collapsed;
MediaTrack? mediaTrack;
try
{
mediaTrack = _mediaPlayer.Media?.Tracks?.FirstOrDefault(x => x.TrackType == TrackType.Video);
}
catch (Exception)
{
mediaTrack = null;
}
if (mediaTrack == null || !mediaTrack.HasValue)
{
return;
}
//get windows scale factor(DPI)
PresentationSource source = PresentationSource.FromVisual(this);
double dpiX=1.0, dpiY=1.0;
if (source != null)
{
dpiX = source.CompositionTarget.TransformToDevice.M11;
dpiY = source.CompositionTarget.TransformToDevice.M22;
}
var displayW = this.Width * dpiX;
var displayH = this.Height * dpiY;
var videoSwapped = mediaTrack.Value.Data.Video.Orientation == VideoOrientation.LeftBottom ||
mediaTrack.Value.Data.Video.Orientation == VideoOrientation.RightTop;
var videoW = mediaTrack.Value.Data.Video.Width;
var videoH = mediaTrack.Value.Data.Video.Height;
if (videoSwapped)
{
var swap = videoW;
videoW = videoH;
videoH = swap;
}
if (mediaTrack.Value.Data.Video.SarNum != mediaTrack.Value.Data.Video.SarDen)
videoW = videoW * mediaTrack.Value.Data.Video.SarNum / mediaTrack.Value.Data.Video.SarDen;
var ar = videoW / (float)videoH;
var dar = displayW / (float)displayH;
float scale;
if (dar >= ar)
scale = (float)displayW / videoW; /* horizontal */
else
scale = (float)displayH / videoH; /* vertical */
//keep ratio of width/height, not fill the srceen
//_mediaPlayer.Scale = scale; // 这是保持视频宽高比的,视频不会变形
//_mediaPlayer.AspectRatio = string.Empty;//这是保持视频宽高比的,视频不会变形
//这是视频变形适配屏幕的情况(满屏)
//fill all the screen by video,video is streched
float xscale, yscale;
xscale = (float)(displayW / videoW);
yscale = (float)(displayH / videoH);
_mediaPlayer.Scale = (xscale<yscale)? xscale:yscale;
string aspectRatio = String.Format("{0}:{1}",
this.Width,this.Height);
_mediaPlayer.AspectRatio = aspectRatio;
}
}
I want to stretch my map on a click of a toolbar button.
I succeed in that simply to go to another page (MapFullPage).
The problem is when I want on override BackButtonPressed through App.Current.Main = new MainMasterDetailPage(new MapPage()) it throwes me back, but my zoom isn't more desired zoom (when I leaved this page and went on MapFullPage), the zoom is small (I can see continents).
If I call App.Current.Main = new MapPage() it shows me the correct zoom.
Here is my two classes:
MapPage ->
public class MapPage : ContentPageCustom
{
//TKCustomMap mapView;
//TKCustomMapPin pinSelected;
DealerLocationResponseModel responseLocations;
DealerLocationResponseModel responseShops;
DealerLocationResponseModel responseStats;
DealerLocationResponseModel responseMoney;
public MapPage()
{
try
{
if (IsBusy)
return;
IsBusy = true;
this.CreateView();
}
catch (Exception ex)
{
DisplayAlert("Error", Constants.StandardError, "OK");
}
finally
{
IsBusy = false;
}
}
private async void CreateView()
{
try
{
Icon = "map-alt.png";
Title = "Locations";
var mapView = new TKCustomMap();
mapView.IsShowingUser = true;
mapView.SetBinding(TKCustomMap.CustomPinsProperty, "Pins");
mapView.SetBinding(TKCustomMap.MapClickedCommandProperty, "MapClickedCommand");
mapView.SetBinding(TKCustomMap.MapLongPressCommandProperty, "MapLongPressCommand");
mapView.SetBinding(TKCustomMap.MapCenterProperty, "MapCenter");
mapView.SetBinding(TKCustomMap.PinSelectedCommandProperty, "PinSelectedCommand");
mapView.SetBinding(TKCustomMap.SelectedPinProperty, "SelectedPin");
mapView.SetBinding(TKCustomMap.RoutesProperty, "Routes");
mapView.SetBinding(TKCustomMap.PinDragEndCommandProperty, "DragEndCommand");
mapView.SetBinding(TKCustomMap.CirclesProperty, "Circles");
mapView.SetBinding(TKCustomMap.CalloutClickedCommandProperty, "CalloutClickedCommand");
mapView.SetBinding(TKCustomMap.PolylinesProperty, "Lines");
mapView.SetBinding(TKCustomMap.PolygonsProperty, "Polygons");
mapView.SetBinding(TKCustomMap.MapRegionProperty, "MapRegion");
mapView.SetBinding(TKCustomMap.RouteClickedCommandProperty, "RouteClickedCommand");
mapView.SetBinding(TKCustomMap.RouteCalculationFinishedCommandProperty, "RouteCalculationFinishedCommand");
mapView.SetBinding(TKCustomMap.TilesUrlOptionsProperty, "TilesUrlOptions");
mapView.SetBinding(TKCustomMap.MapFunctionsProperty, "MapFunctions");
mapView.IsRegionChangeAnimated = true;
NavigationPage.SetHasBackButton(this, false);
BackgroundColor = Color.White;
responseLocations = ServiceProvider.GetDealerLocationServiceMethod(new DealerLocationRequestModel { MobilePhoneNumber = "063333333", UserIdentificator = "1234" });
if (!responseLocations.Succeeded)
{
await DisplayAlert("Greska", "Nije nadjena nijedna lokacija", "OK");
App.Current.MainPage = new HomeMasterDetail();
return;
}
List<TKCustomMapPin> pinLists = new List<TKCustomMapPin>();
foreach (var item in responseLocations.Dealers)
{
pinLists.Add(
new TKCustomMapPin
{
Image = "_mapPin_36x36",
IsCalloutClickable = true,
ShowCallout = true,
Position = new Position(item.Latitude, item.Longitude),
Title = item.LocationName + " " + item.Address,
Subtitle = item.LocationDescription
}
);
}
mapView.CustomPins = pinLists;
#region Stack and Buttons
mapView = new TKCustomMap(MapSpan.FromCenterAndRadius(mapView.CustomPins.ElementAt(1).Position, Distance.FromKilometers(2)));
mapView.CustomPins = new List<TKCustomMapPin>(pinLists);
mapView.IsShowingUser = true;
StackLayout btnCart = ElementsHelper.createImageButton("_cart_512x512.png", "Shops");
StackLayout btnStats = ElementsHelper.createImageButton("_stats_512x512.png", "Top up");
StackLayout btnMoney = ElementsHelper.createImageButton("_money_512x512.png", "Cash out");
StackLayout layout = new StackLayout
{
Orientation = StackOrientation.Horizontal,
HorizontalOptions = LayoutOptions.Center,
Children =
{
btnStats,
btnMoney,
btnCart
}
};
BoxView box1 = new BoxView { BackgroundColor = Color.Transparent, HeightRequest = Device.GetNamedSize(NamedSize.Large, typeof(Image)) * 2.5, WidthRequest = Device.GetNamedSize(NamedSize.Large, typeof(Image)) * 2.5 };
BoxView box2 = new BoxView { BackgroundColor = Color.Transparent, HeightRequest = Device.GetNamedSize(NamedSize.Large, typeof(Image)) * 2.5, WidthRequest = Device.GetNamedSize(NamedSize.Large, typeof(Image)) * 2.5 };
ActivityIndicator activityIndicator = new ActivityIndicator();
activityIndicator.Color = Constants.iPink;
activityIndicator.BindingContext = this;
activityIndicator.IsRunning = true;
activityIndicator.HeightRequest = 70;
activityIndicator.Margin = new Thickness(15, 0);
activityIndicator.SetBinding(ActivityIndicator.IsRunningProperty, "IsBusy");
activityIndicator.SetBinding(ActivityIndicator.IsVisibleProperty, "IsBusy");
layout.Children.Add(activityIndicator);
StackLayout layoutIndicator = new StackLayout { Orientation = StackOrientation.Horizontal };
layoutIndicator.Children.Add(box1);
layoutIndicator.Children.Add(activityIndicator);
layoutIndicator.Children.Add(box2);
layoutIndicator.IsVisible = false;
TapGestureRecognizer btnShopRecognizer = new TapGestureRecognizer();
btnShopRecognizer.Tapped += async (sender, e) =>
{
if (IsBusy)
return;
IsBusy = true;
layout.IsVisible = false;
layoutIndicator.IsVisible = true;
await Task.Delay(400);
responseShops = ServiceProvider.GetDealerLocationServiceMethod(new DealerLocationRequestModel { MobilePhoneNumber = "063333333", UserIdentificator = "1234" }, 1);
SetPins(mapView, responseShops);
mapView.MoveToRegion(MapSpan.FromCenterAndRadius(new Position(responseShops.Dealers.ElementAt(1).Latitude, responseShops.Dealers.ElementAt(1).Longitude), Distance.FromKilometers(2)));
SetActiveButtonMap(btnCart, btnStats, btnMoney);
IsBusy = false;
layoutIndicator.IsVisible = false;
layout.IsVisible = true;
};
TapGestureRecognizer btnMoneyRecognizer = new TapGestureRecognizer();
btnMoneyRecognizer.Tapped += async (sender, e) =>
{
if (IsBusy)
return;
IsBusy = true;
layout.IsVisible = false;
layoutIndicator.IsVisible = true;
await Task.Delay(400);
responseMoney = ServiceProvider.GetDealerLocationServiceMethod(new DealerLocationRequestModel { MobilePhoneNumber = "063333333", UserIdentificator = "1234" }, 2);
SetPins(mapView, responseMoney);
mapView.MoveToRegion(MapSpan.FromCenterAndRadius(new Position(responseMoney.Dealers.ElementAt(1).Latitude, responseMoney.Dealers.ElementAt(1).Longitude), Distance.FromKilometers(2)));
SetActiveButtonMap(btnMoney, btnStats, btnCart);
IsBusy = false;
layoutIndicator.IsVisible = false;
layout.IsVisible = true;
};
TapGestureRecognizer btnStatsRecognizer = new TapGestureRecognizer();
btnStatsRecognizer.Tapped += async (sender, e) =>
{
if (IsBusy)
return;
IsBusy = true;
layout.IsVisible = false;
layoutIndicator.IsVisible = true;
await Task.Delay(400);
responseStats = ServiceProvider.GetDealerLocationServiceMethod(new DealerLocationRequestModel { MobilePhoneNumber = "063333333", UserIdentificator = "1234" }, 3);
SetPins(mapView, responseStats);
mapView.MoveToRegion(MapSpan.FromCenterAndRadius(new Position(responseStats.Dealers.ElementAt(1).Latitude, responseStats.Dealers.ElementAt(1).Longitude), Distance.FromKilometers(2)));
SetActiveButtonMap(btnStats, btnMoney, btnCart);
IsBusy = false;
layoutIndicator.IsVisible = false;
layout.IsVisible = true;
};
btnCart.GestureRecognizers.Add(btnShopRecognizer);
btnMoney.GestureRecognizers.Add(btnMoneyRecognizer);
btnStats.GestureRecognizers.Add(btnStatsRecognizer);
#endregion
RelativeLayout _baseLayout = new RelativeLayout { VerticalOptions = LayoutOptions.FillAndExpand };
_baseLayout.Children.Add(
mapView,
Constraint.RelativeToParent((parent) =>
{
return (0);
}),
Constraint.RelativeToParent((parent) =>
{
return (0);
}),
heightConstraint: Constraint.RelativeToParent((r) => r.Height),
widthConstraint: Constraint.RelativeToParent((r) => r.Width));
Func<RelativeLayout, double> getLayoutWidth = (p) => layout.Measure(_baseLayout.Width, _baseLayout.Height).Request.Width;
_baseLayout.Children.Add(layout,
Constraint.RelativeToParent((parent) => parent.Width / 2 - getLayoutWidth(parent) / 2),
Constraint.RelativeToParent((parent) =>
{
return (.8 * parent.Height);
})
);
_baseLayout.Children.Add(layoutIndicator,
Constraint.RelativeToParent((parent) => parent.Width / 2 - getLayoutWidth(parent) / 2),
Constraint.RelativeToParent((parent) =>
{
return (.8 * parent.Height);
})
);
//_baseLayout.Children.Add(activityIndicator,
//Constraint.RelativeToParent((parent) => parent.Width / 2),
//Constraint.RelativeToParent((parent) =>
//{
// return (.8 * parent.Height);
//})
//);
Constraint.RelativeToParent((parent) =>
{
return (1);
});
_baseLayout.HeightRequest = App.ScreenHeight - 200;
Content = _baseLayout;
}
catch
{
await DisplayAlert("Error", Constants.StandardError, "OK");
}
//this._baseLayout.Children.Add(
// mapView,
// Constraint.RelativeToView(autoComplete, (r, v) => v.X),
// Constraint.RelativeToView(autoComplete, (r, v) => autoComplete.HeightOfSearchBar),
// heightConstraint: Constraint.RelativeToParent((r) => r.Height - autoComplete.HeightOfSearchBar),
// widthConstraint: Constraint.RelativeToView(autoComplete, (r, v) => v.Width));
//this._baseLayout.Children.Add(
// autoComplete,
// Constraint.Constant(0),
// Constraint.Constant(0));
}
private void SetPins(TKCustomMap map, DealerLocationResponseModel dealerModel = null)
{
List<TKCustomMapPin> pinLists = new List<TKCustomMapPin>();
foreach (var item in dealerModel.Dealers)
{
pinLists.Add(
new TKCustomMapPin
{
Image = "_mapPin_36x36",
IsCalloutClickable = true,
ShowCallout = true,
Position = new Position(item.Latitude, item.Longitude),
Title = item.LocationName + " " + item.Address,
Subtitle = item.LocationDescription,
}
);
}
//map.CustomPins = null;
map.CustomPins = pinLists;
}
private void SetActiveButtonMap(StackLayout activeImage, StackLayout disabledImage1, StackLayout disabledImage2)
{
var a = ((activeImage.Children[0] as Image).Source as FileImageSource).File;
if ((!((activeImage.Children[0] as Image).Source as FileImageSource).File.ToString().Contains("_active")))
//Set active image
StartClickCustom(activeImage.Children[0] as Image);
//Remove active images
if (((disabledImage1.Children[0] as Image).Source as FileImageSource).File.ToString().Contains("_active"))
{
EndClickCustom(disabledImage1.Children[0] as Image);
}
if (((disabledImage2.Children[0] as Image).Source as FileImageSource).File.ToString().Contains("_active"))
{
EndClickCustom(disabledImage2.Children[0] as Image);
}
}
}
and MapFullPage is the same (copy/pasted) just has onBack method:
protected override bool OnBackButtonPressed()
{
App.fromBack = true;
App.Current.MainPage = new MainMasterDetailPage(new MapPage());
return true;
}
I am stuck on Navigating Pages in my app. I am beginner to Xamarin Form. What i am doing is i have a Master Details Page called master.cs by default it navigates to home page i.e. content page. I have created list view in other class page i.e. ModelClasses.cs now i want to navigate to other content pages while select listview item. i tried lot more things but not working.
HELP ME!!
MasterPage
public class master : MasterDetailPage
{
public master ()
{
Label header = new Label {
Text = "Master",
Font = Font.BoldSystemFontOfSize (20)
};
MenuStacklayout _MenuStacklayout = new MenuStacklayout ();
this.Master = new ContentPage{
Title=header.Text,
Content=_MenuStacklayout
};
this.Detail = new NavigationPage(new FTWHome());
// For Windows Phone, provide a way to get back to the master page.
if (Device.OS == TargetPlatform.WinPhone)
{
(this.Detail as ContentPage).Content.GestureRecognizers.Add(
new TapGestureRecognizer((view) =>
{
this.IsPresented = true;
}));
}
}
}
ModelClasses
MenuStacklayout Creates a Menu
public class MenuStacklayout : StackLayout
{
String[] homelinks = { "HOME" };
String[] healthlinks = { "I NEED HELP", "A MATE NEEDS HELP", "MOOD TRACKER", "HELPFUL ARTICLES" };
String[] entertainmentlinks = { "PHOTO OF THE DAY", "MAGZINE CONTENTS", "FTW TEAM" };
String[] aboutlinks = { "FTW PHILOSOPHY", "ABOUT FTW", "FTW STORE", "FTW SOCIAL" };
String[] joinftwlinks = { "JOIN FTW" };
String[] loginlinks = { "LOGIN" };
#region Menu Layout
public MenuStacklayout ()
{
ListView homelist = new ListView {
ItemsSource = menuitems._menuitems (homelinks),
ItemTemplate = new DataTemplate (typeof(ftwMenuCell))
};
homelist.RowHeight = 30;
homelist.ItemSelected+= navigatePage_onSelected;
StackLayout homeliststack = new StackLayout ();
homeliststack.Children.Add (homelist);
homelist.SeparatorVisibility = SeparatorVisibility.None;
//homeliststack.Padding = new Thickness (2, 5, 0, 0);
ListView healthlist = new ListView {
//Header = "HEALTH",
ItemsSource = menuitems._menuitems (healthlinks),
ItemTemplate = new DataTemplate (typeof(ftwMenuCell))
};
healthlist.RowHeight = 30;
healthlist.ItemSelected+=navigatePage_onSelected;
StackLayout healthliststack = new StackLayout ();
healthliststack.Children.Add (healthlist);
healthlist.SeparatorVisibility = SeparatorVisibility.None;
ListView entertainmentlist = new ListView {
//Header = "ENTERTAINMENT",
ItemsSource = menuitems._menuitems (entertainmentlinks),
ItemTemplate = new DataTemplate (typeof(ftwMenuCell))
};
entertainmentlist.RowHeight = 30;
entertainmentlist.ItemSelected+=navigatePage_onSelected;
StackLayout entertainmentliststack = new StackLayout ();
entertainmentliststack.Children.Add (entertainmentlist);
entertainmentlist.SeparatorVisibility = SeparatorVisibility.None;
ListView aboutlist = new ListView {
//Header = "ABOUT",
ItemsSource = menuitems._menuitems (aboutlinks),
ItemTemplate = new DataTemplate (typeof(ftwMenuCell))
};
aboutlist.RowHeight = 30;
aboutlist.ItemSelected+=navigatePage_onSelected;
StackLayout aboutliststack = new StackLayout ();
aboutliststack.Children.Add (aboutlist);
aboutlist.SeparatorVisibility = SeparatorVisibility.None;
ListView joinftwlist = new ListView {
ItemsSource = menuitems._menuitems (joinftwlinks),
ItemTemplate = new DataTemplate (typeof(ftwMenuCell))
};
joinftwlist.RowHeight = 30;
StackLayout joinftwliststack = new StackLayout ();
joinftwliststack.Children.Add (joinftwlist);
joinftwlist.SeparatorVisibility = SeparatorVisibility.None;
ListView loginlist = new ListView {
ItemsSource = menuitems._menuitems (loginlinks),
ItemTemplate = new DataTemplate (typeof(ftwMenuCell))
};
loginlist.RowHeight = 30;
loginlist.SeparatorVisibility = SeparatorVisibility.None;
loginlist.BackgroundColor = Color.Blue;
StackLayout loginstack = new StackLayout ();
loginstack.Children.Add (loginlist);
this.Spacing = 1;
this.BackgroundColor = Color.FromHex("#cccccc");
this.Padding = new Thickness (0, 65, 0, 0);
this.Orientation = StackOrientation.Vertical;
this.VerticalOptions = LayoutOptions.StartAndExpand;
this.Children.Add (homeliststack);
this.Children.Add (healthliststack);
this.Children.Add (entertainmentliststack);
this.Children.Add (aboutliststack);
this.Children.Add (joinftwlist);
this.Children.Add (loginstack);
}
}
ItemTemplate For Menu
public class ftwMenuCell : ViewCell
{
public ftwMenuCell ()
{
var nameLabel = new Label () {
FontFamily = "HelveticaNeue-Medium",
FontSize = 14,
FontAttributes=FontAttributes.Bold,
TextColor = Color.Black,
VerticalOptions=LayoutOptions.Center
};
nameLabel.SetBinding (Label.TextProperty, "_link");
var cellLayout = new StackLayout {
Spacing = 0,
Padding = new Thickness (10, 0, 0, 0),
VerticalOptions=LayoutOptions.FillAndExpand,
Orientation = StackOrientation.Horizontal,
Children = { nameLabel }
};
this.View = cellLayout;
}
}
public class _menulink
{
public string _link{ get; set; }
}
public static class menuitems
{
public static List<_menulink> _menuitems (string[] linkid)
{
List<_menulink> menulinklist = new List<_menulink> ();
foreach (var item in linkid) {
_menulink menulink = new _menulink ();
menulink._link = item;
menulinklist.Add (menulink);
}
return menulinklist;
}
}
i have respective content page for Every Listview Item.
THANKS IN ADVANCE!!
I can't see where you navigatePage_onSelected is declared but you could try something like
void navigatePage_onSelected(object sender, SelectedItemChangedEventArgs e) {
Navigation.PushModalAsync(new PageName());
}
Let me know if that works out for you :)
I have solved it !!
in my navigatePage_onSelected event handler which is declared in MenuStacklayout Class i put following code and it's working.
void navigatePage_onSelected(object sender, SelectedItemChangedEventArgs args){
_menulink menuitem = (_menulink)args.SelectedItem;
MasterDetailPage mstr = (MasterDetailPage)(Application.Current.MainPage); // My Application main page is a Masterpage so..
if (menuitem._link == "ABOUT FTW") {
mstr.Detail = new NavigationPage (new AboutFTW ());
}else if(menuitem._link == "I NEED HELP"){
mstr.Detail = new NavigationPage (new Entertainment ());
}else if(menuitem._link == "HOME"){
mstr.Detail = new NavigationPage (new FTWHome ());
}
// Show the detail page.
mstr.IsPresented = false;
}