MVVMCross 4.1.4 Composite Views - mvvmcross

Iam currently trying to implement composite views in my app for the tablet layout, so i dont need the Viewpager and TabLayout which is used in the phone layout.
But apparently it is not as easy as i thought it would be and the examples/tutorials which i found are made for the older version of MVVMCross.
My idea was just to search for the viewpager, if it is not found in the current layout, then check for the framelayouts and show my two different viewmodels like i did with the MvxFragmentPagerAdapter for the Viewpager/Tablayout.
Is there any "clean" solution for this?
Thank you for you time!

I found a acceptable answer by using FragmentTransactions. Here is the simplified code. Though iam kinda abusing the MvxFragmentPagerAdapter.GetItem(index) here for the Fragment and ViewModel Initialization (https://github.com/MvvmCross/MvvmCross-AndroidSupport/blob/master/MvvmCross.Droid.Support.V4/MvxFragmentPagerAdapter.cs) :
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
var view = base.OnCreateView(inflater, container, savedInstanceState);
var viewPager = view.FindViewById<ViewPager>(Resource.Id.viewpager);
var fragments = new List<MvxFragmentPagerAdapter.FragmentInfo> {
new MvxFragmentPagerAdapter.FragmentInfo("Fragment1", typeof(FragmentOne),
typeof(FragmentViewModelOne)),
new MvxFragmentPagerAdapter.FragmentInfo("Fragment2", typeof(FragmentTwo),
typeof(FragmentViewModelTwo))
};
var adapter = new MvxFragmentPagerAdapter(Activity, ChildFragmentManager, fragments);
if (viewPager != null)
{
viewPager.Adapter = adapter;
var tabLayout = view.FindViewById<TabLayout>(Resource.Id.tabs);
if (tabLayout != null)
{
tabLayout.SetupWithViewPager(viewPager);
}
}
else
{
FragmentTransaction transaction = FragmentManager.BeginTransaction();
transaction.Replace(Resource.Id.frameone, adapter.GetItem(0), "Fragment1");
transaction.Replace(Resource.Id.frametwo, adapter.GetItem(1), "Fragment2");
transaction.Commit();
}
return view;
}
If there is a better solution, dont be shy! =)
Greetings Cyriac

Related

Reference to type GoogleMap.IOnCameraMoveListener claims it is defined in Xamarin.GooglePlayServices

I'm facing an issue related with a reference, as the title shows I'm getting:
Reference to type 'GoogleMap.IOnCameraMoveListener' claims it is
defined in 'Xamarin.GooglePlayServices.Maps', but it could not be
found C:\Users\App.Xamarin\App.Android\CustomMapRenderer.cs
I been trying to use the live player on a Samsung Galaxy S8+ Android API 27 with no success.
using Android.Gms.Maps.Model;
using App.Android;
using App.Portable.Vista.ControlesUsuario.Mapas;
using System.Collections.Generic;
using Xamarin.Forms;
using Xamarin.Forms.Maps;
using Xamarin.Forms.Maps.Android;
[assembly: ExportRenderer(typeof(MapaGoogle), typeof(CustomMapRenderer))]
namespace App.Android
{
public class CustomMapRenderer : MapRenderer
{
List<Position> routeCoordinates;
bool isDrawn;
protected override void OnElementChanged(Xamarin.Forms.Platform.Android.ElementChangedEventArgs<Map> e)
{
base.OnElementChanged(e);
if (e.OldElement != null)
{
// Unsubscribe
}
if (e.NewElement != null)
{
var formsMap = (MapaGoogle)e.NewElement;
routeCoordinates = formsMap.RouteCoordinates;
Control.GetMapAsync(this);
}
}
protected override void OnElementPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName.Equals("VisibleRegion") && !isDrawn)
{
var polylineOptions = new PolylineOptions();
polylineOptions.InvokeColor(0x66FF0000);
foreach (var position in routeCoordinates)
{
polylineOptions.Add(new LatLng(position.Latitude, position.Longitude));
}
NativeMap.AddPolyline(polylineOptions);
isDrawn = true;
}
}
}
}
I spent 2 days already trying to figure out what's going on but it is quite hard to find a solution as the error is too specific if I am not mistaken.
I only found this link with relevant information.
Also, I do not know if it is related with the NuGet packages that require updates GooglePlayServices, Forms and so on. However, whenever I update them the references are missed in the whole solution.
Any help will be highly appreciated !
Cheers,
Eric R.

Update text block from downloaded text file = RPC_E_WRONG_THREAD WP8.1

I am learning Windows Phone 8.1 development, I have probably done something utterly incorrectly programming wise
The need: I want to download a text file from the web using HttpClient() and display it in the TextBlock1
From variety of tutorials I have found the following:
public async void DownloadDataAsync()
{
string data = "some link to Textfile.txt";
HttpClient client = new HttpClient();
HttpResponseMessage response = await client.GetAsync(data);
HttpContent content = response.Content;
string result = await content.ReadAsStringAsync();
UpdateTextBlock1(result);
}
Then the other functions.
public void UpdateTextBlock1(string result)
{
TextBlock1.Text = result;
}
private void BtnDownloadData_Click(object sender, RoutedEventArgs e)
{
Task t = new Task(DownloadDataAsync);
t.Start();
}
The code starts well enough - on button pressed, I receive RPC_E_WRONG_THREAD.
Is it that I'm trying to call the method when all threads haven't finished? How can I code that efficently so the TextBlock1 is updated with txt data?
Thanks for understanding, baby steps here in programming, and I couldn't find a relevant answer over google. (Maybe I don't yet know how to ask?)
You need to update the textblock on the UI thread like so:
Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
TextBlock1.Text = result;
});
There are many posts on this subject.

CameraPreviewImageSource empty preview frame

I made cut and paste of the code below about how to use CameraPreviewImageSource and access to preview buffer frames, but do not work and it seems the frame buffer size is 0x0 reading the value of IImageSize parameter of OnPreviewFrameAvailable event.
How to get preview buffer of MediaCapture - Universal app
protected override void OnNavigatedTo(NavigationEventArgs e)
{
InitializeAsync();
}
public async void InitializeAsync()
{
_cameraPreviewImageSource = new CameraPreviewImageSource();
await _cameraPreviewImageSource.InitializeAsync(string.Empty);
var properties = await _cameraPreviewImageSource.StartPreviewAsync();
var width = 640.0;
var height = 480;
_writeableBitmap = new WriteableBitmap((int)width, (int)height);
_writeableBitmapRenderer = new WriteableBitmapRenderer(_cameraPreviewImageSource, _writeableBitmap);
Initialized = true;
_cameraPreviewImageSource.PreviewFrameAvailable += OnPreviewFrameAvailable;
}
private async void OnPreviewFrameAvailable(IImageSize args)
{
System.Diagnostics.Debug.WriteLine("ww:"+args.Size.Width+" hh:"+args.Size.Height);
// Prevent multiple rendering attempts at once
if (Initialized && !_isRendering)
{
_isRendering = true;
try
{
await _writeableBitmapRenderer.RenderAsync();
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine("\n\n"+ex.Message);
System.Diagnostics.Debug.WriteLine(ex.StackTrace);
}
_isRendering = false;
}
}
Capabilities (webcam & microphone) on Package.appxmanifest has been selected
Implementing CameraPreviewImageSource on a Silverlight app works great!
I am afraid you are (were) seeing a bug in Lumia Imaging SDK 2.0.184. The problem only occured on some camera models and only on 8.1/universal applications. Silverlight applications were not affected by the problem.
The bug has been fixed in the newly released Lumia Imaging SDK 2.0.208. From release notes:
Fixed ArgumentOutOfRangeException being thrown by CameraPreviewImageSource when used with certain camera models.

Get error "InvalidRequest" when use AdMob in WP8

I'm really confusing ! I get this error randomly, Sometime the code worked (yesterday code went okay) but sometime not (today it returned "InvalidRequest" error).
I put this code in every page of my app
public MainPage()
{
InitializeComponent();
DataContext = App.MyModel;
LoadAd();
}
void LoadAd()
{
AdView av = new AdView()
{
AdUnitID = "ca-app-pub-...‏‏‏‏‏",
Format = AdFormats.Banner,
VerticalAlignment = System.Windows.VerticalAlignment.Top,
HorizontalAlignment = System.Windows.HorizontalAlignment.Left,
};
av.FailedToReceiveAd += av_FailedToReceiveAd;
LayoutRoot.Children.Add(av);
AdRequest ar = new AdRequest();
ar.ForceTesting = true;
av.LoadAd(ar);
}
void av_FailedToReceiveAd(object sender, AdErrorEventArgs e)
{
Debug.WriteLine(e.ErrorCode.ToString());
}
I have found out that this error is mostly due to incorrect ad unit ids.
Check your adid, and make sure that its correct and doesnt have any space

Binding doesn't work in MVVM in WP8

I am new in the development of WP8. I have been following a online course for a couple of weeks and the second task of the course was to develop a app to show the weather, some news and photos related to the city.
So far, I have develop the app following the MVVM pattern using the Panorama control as the conteiner for the differents contents I need to show.
To no longer this, the problem I facing is at the moment to display the xml data that is retrieve from the webservices.
The XAML is:
<phone:panorama x:Name="myPanorama"
DataContext = {Binding Source="WeatherViewModel"}>
<PanoramaItem header="MyWeather">
<Textblock x:name="txtCity"
Text = {Binding Weather.City}
</Textblock>
</PanoramaItem>
<panoramaItem header="Config">
<Text x:Name="txtGetCity"/>
<Button x:Name="btnGetCity"
Command={Binding GetWeatherCommand}/>
</panoramaItem>
</phone:panorama>
My ViewModel:
public class WeaterViewModel : NotificationEnableObject
{
private Weather _currentWeather;
public Weather GetCurrentWeather
{
get
{
if (_currentWeather == null)
_currentWeather = new Weather();
return _currentWeather;
}
set { _currentWeather = value;
OnPropertyChanged("GetCurrentWeather");
}
}
//Constructor ServiceModel serviceModel = new ServiceModel();
public WeatherViewModel()
{
serviceModel.GetWeatherCompleted += (s, a) =>
{
_currentWeather = new Clima();
_currentWeather.City= a.Results[0].City;
_currentWeather.tempC = a.Results[0].tempC;
};
getWeatherCommand = new ActionCommand(null);
}
ActionCommand getWeatherCommand; // ActionCommand derivied from ICommand
public ActionCommand GetWeatherCommand
{
get
{
if (getWeatherCommand!= null)
{
getWeatherCommand = new ActionCommand(() =>
{
//Call the Service who retrieved the data
});
}
return getWeatherCommand;
}
}
}
The Weather specified is a public class which contain the City property. I have tried using an IObservableCollention as well howerver, the result is the same :-(
As you can see in the panorama control I have 2 sections. The one where I write the city I wanna see and the section where I show the information I get from the web services.
Any clue, or help would be very appreciate
Regards!
Ok, I think that is an easy fix.
You're setting GetCurrentWeather this way:
_currentWeather = new Clima();
_currentWeather.City= a.Results[0].City;
_currentWeather.tempC = a.Results[0].tempC;
This is not firing the PropertyChanged event. Change it to:
GetCurrentWeather= new Clima();
GetCurrentWeather.City= a.Results[0].City;
GetCurrentWeather.tempC = a.Results[0].tempC;
and you should be fine.