How do you implement a Dictionary in XAML in XAMARIN? - xamarin

Being an advocate of MVVM design, I only work with enums in my view models for graphics objects. I defer the association to an actual bitmap until the view needs a bitmap. In WPF and UWP, I used a dictionary that looked like this:
<trcontrols:UriCategory>
<trcontrols:UriSource x:Key="Alert"
Uri="ms-appx:///ThetaRex.InvestmentManager.Views/Assets/Banner/Alert.png"/>
<trcontrols:UriSource x:Key="Application"
Uri="ms-appx:///ThetaRex.InvestmentManager.Views/Assets/Banner/Application.png"/>
<trcontrols:UriSource x:Key="Folder"
Uri="ms-appx:///ThetaRex.InvestmentManager.Views/Assets/Banner/Folder.png"/>
<trcontrols:UriSource x:Key="Blotter"
Uri="ms-appx:///ThetaRex.InvestmentManager.Views/Assets/Banner/Blotter.png"/>
<trcontrols:UriSource x:Key="Portfolio"
Uri="ms-appx:///ThetaRex.InvestmentManager.Views/Assets/Banner/Portfolio.png"/>
</trcontrols:UriCategory>
This code doesn't port to XAMARIN. This is what works in WPF and UWP:
[ContentProperty("Content")]
public class UriCategory
{
public UriCategory()
{
this.Content = new Dictionary<string, string>();
}
public IDictionary Content { get; }
}
But in XAMARIN, I get 'Sequence contains no matching element'. It looks like it's trying some LINQ 'First' operation, but I can't extract anything useful out of the call stack.
Does anyone have an implementation of a Dictionary in XAML in XAMARIN that they can share?

Related

Want to Send the Object type data from one VSTO addin Project to Another VSTO addin project

I am working on a Outlook addin in which I want to send the data from one outlook addin project to another outlook project. But when I try call the function of another project with the object type data in the arguments it will throw "Unable to cast object of type 'System.Runtime.Remoting.Proxies.__TransparentProxy' to type at System.Runtime.InteropServices.Marshal.ThrowExceptionForHRInternal(Int32 errorCode, IntPtr errorInfo)" error.
Here is the code for your reference.
public IProfileAttribute[] profileAttributes= null;
Outlook.Application outlookApp = new Outlook.Application();
this.profileAttributes = new FilingNotifiableIpmlementation().FilingNotification(); // to fill the object
object destAddinName = "Tikit.CarpeDiem.AddIn.Outlook";
Office.COMAddIn destAddIn = outlookApp.COMAddIns.Item(ref destAddinName)
destAddIn.Object.FilingNotification(this.profileAttributes);
FilingNotification() is the method which we want to call of Tikit.CarpeDiem.AddIn.Outlook this project and this.profileAttributes is the object array.
The flow is going perfectly to the Outlook project if the parameter type is either string or int but it is throwing error if the parameter is object type.
Implementation of FilingNotification() method in Tikit.CarpeDiem.AddIn.Outlook project.
public void FilingNotification(IProfileAttribute[] profileAttributesList)
{
if (profileAttributesList != null)
{
var x = profileAttributesList;
}
else
{
string y = "Try again";
}
}
Can someone help me in this one. I am stuck in this for 2 days. It will be really helpful. Thanks in advance.
Instead of passing a .Net object, make it implement a COM interface and pass it as an interface:
var obj = new MyBlah();
destAddIn.Object.FilingNotification(obj as IBlah);
...
[ComVisible(true)]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface IBlah
{
void DoBlah();
}
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
public class MyBlah: StandardOleMarshalObject, IBlah
{
public void DoBlah()
{
//todo
};
}
You may pass scalar data types following that way. You need to implement an interface known on both sides if you want to pass objects between two entities. Read more about that in the Walkthrough: Call code in a VSTO Add-in from VBA article. For example:
[ComVisible(true)]
public interface IAddInUtilities
{
void ImportData();
}
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
public class AddInUtilities : IAddInUtilities
{
// This method tries to write a string to cell A1 in the active worksheet.
public void ImportData()
{
// implementation
}
}
Also you may consider using any standard mechanisms available for .net based applications such Remoting or WCF, see Basic WCF programming for more information.

ViewModel not resolved

I have a UWP Application using ReactiveUI. I navigate to a page with this code:
Router.Navigate.Execute(new AccountListViewModel(this));
The navigation is done. But the ViewModel I created for the navigation is not assigned to my ViewModel in the View. IViewFor<> is implemented as follows:
public sealed partial class AccountListView : IViewFor<AccountListViewModel>
{
public static readonly DependencyProperty ViewModelProperty = DependencyProperty
.Register(nameof(ViewModel), typeof(AccountListViewModel), typeof(AccountListView), null);
public AccountListView()
{
this.InitializeComponent();
this.WhenActivated(disposables =>
{
// My Bindings
...
});
}
object IViewFor.ViewModel
{
get => ViewModel;
set => ViewModel = (AccountListViewModel) value;
}
public AccountListViewModel ViewModel {
get => (AccountListViewModel)GetValue(ViewModelProperty);
set => SetValue(ViewModelProperty, value);
}
Or do I get something completly wrong here?
According to ReactiveUI RoutedViewHost implementation for Windows, which is used for Universal Windows Platform and for Windows Presentation Foundation, the view model should definitely get assigned to the IViewFor.ViewModel property. You can track changes in the IScreen.Router.CurrentViewModel property to make sure it changes.
If it does, make sure you properly bind your IScreen.Router property to the Router property of the UWP-specific RoutedViewHost XAML control, and routing should finally work. In fact, I tested that behavior on UWP recently and it worked fine for me with ReactiveUI 9.13.1 and latest UWP SDK. Try following the routing tutorial to fully understand how routing works. If this still won't work for you, then uploading a minimal repro that compiles to GitHub could help us understand your issue better. Also, come join ReactiveUI Slack, we are always ready to help out.

Xamarin SDK for OpenStreetMap

I'm trying to make a Proof of Concept (C#) for basic graphical maps, as an alternative to Google Maps for Andriod and iOS devices - because Google started charging fees for their APIs (from my understanding only affecting web right now).
I doesn't need to be particularly advanced, simply a GUI that shows a base map where you can draw:
Markers
Lines
Polygons
The only requirements I have is that it should be open-source, or at as low a cost as possible.
What I've done so far is to use data from http://openstreetmap.org - and set up a tile-server https://switch2osm.org/serving-tiles/ on a separate linux machine.
Furthermore, it went fairly quick to create a simple web app with OpenLayers.js and Leaflet.js connected to the custom tile-server with the requirments met.
What I need to do now is to find a free or cheap mobile SDK for Xamarin for Android and iOS. I managed to render a map from my own tile-server and add markers by referring .dll's from this zip from 2014 (only tested for Andriod): https://github.com/OsmSharp/ui/releases/tag/v4.2.0.723
using OsmSharp.Android.UI;
using OsmSharp.Android.UI.Data.SQLite;
using OsmSharp.Math.Geo;
using OsmSharp.UI.Map;
using OsmSharp.UI.Map.Layers;
[Activity(Label = "#string/app_name", MainLauncher = true)]
public class MainActivity : AppCompatActivity
{
private MapView _mapView { get; set; }
private Layer _mapLayer { get; set; }
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
try
{
Native.Initialize();
_mapView = new MapView(this, new MapViewSurface(this))
{
MapTilt = 0,
MapCenter = new GeoCoordinate(lat, long),
MapZoom = 16,
Map = new Map()
};
// create a marker under Resources/drawable/pin.png
using (var bitmap = BitmapFactory.DecodeResource(Resources, Resource.Drawable.pin))
{
var marker = new MapMarker(this, new GeoCoordinate(lat, long), MapMarkerAlignmentType.CenterBottom, bitmap);
_mapView.AddMarker(marker);
}
_mapLayer = _mapView.Map.AddLayerTile("http://*.*.*.*/{0}/{1}/{2}.png");
SetContentView(_mapView);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
}
However, these .dlls seemed to lack support for Lines and Polygons. I have tried to get something similar to work with OsmSharp's latest NuGet package (2018-06-04), but my novice Xamarin experiance only gets me so far.
Does anyone have any tips on how to use my own tile-server and render native maps on Android and iOS devices?
PS. It doen't strictly need to be OpenStreetMap with OsmSharp connected to a custom tile-server, that's just something im leaning towards right now. Again, requirents are open-source or at a low cost with the fexebility to add Markers, Lines and Polygons.

How can I code a class to receive a property for use with custom renderers?

I have seen this coding style:
public CustomTextCell()
{
}
public static readonly BindableProperty IsCheckedProperty =
BindableProperty.Create(
"IsChecked", typeof(bool), typeof(CustomTextCell),
defaultValue: false);
public bool IsChecked
{
get { return (bool)GetValue(IsCheckedProperty); }
set { SetValue(IsCheckedProperty, value); }
}
}
and this:
public class ExtViewCell : ViewCell
{
public bool NoTap { get; set; }
}
Can someone help explain the difference. Is one serving a different function from the other? In my case all I need is to pass to a custom renderer the value of NoTap. Should I code it like in the first or second example?
The second one is a POCO - a plain old C# object - that is relatively self-explanatory, but serves not much more purpose that holding data - and not that much in this case.
The first one is a bit more interesting, especially in the context of MVVM. SetValue does more than just setting the value, but will (in most cases) raise PropertyChanged event (see INotifyPropertyChanged), to notify subscribers that, well, a property has changed.
Now how does this relate to your custom renderer? You could implement the property in your view as a plain property - i.e. without notifications - and it might work (cannot tell, though, since I do not know your custom renderer) when setting IsChecked initially (and without binding). Anyway, imagine you'll update the value of IsChecked. You do so from your code and wonder, why this change is not reflected in your custom renderer. But how is your renderer supposed to know? Polling each and every property might be possible for smaller forms, but is a terrible waste of resources. (And Xamarin.Forms just does not work this way.) You'll page/view has to tell your custom renderer, that something has changed. INotifyPropertyChanged to the rescue. In your custom renderer you can subscribe to PropertyChanged event and react to IsChecked being changed, updating your native view.

Localization and binding don't work together

I'm developing my first app and I'm trying to make it multilanguage.
Using AppHub example and some other link I created my resource files, fixed binding strings on my components and set a settings page.
First problem I had was that menu items and appbar buttons couldn't use localization strings (project complained when launched) so I have:
TextBlocks and other components binded with localized strings
Appbar buttons and items localized manually with a procedure loading localized strings
Now that I have my settings page, one item user can change is language.
Well, correct CultureInfo is selected according to user selection and then I use
Thread.CurrentThread.CurrentUICulture = Settings.Language;
When I press back button and return to main page, appbar items are localized correctly, while everything else is not.
The only workaround (that I really don't like, it's just to understand) is this:
public MainPage()
{
Thread.CurrentThread.CurrentUICulture = Settings.Language;
InitializeComponent();
// Everything else I need here
}
so I have to set language before components are created to make it work.
What's wrong? Which is the correct way to make a page refresh after changing language using binded strings?
I did not put a lot of code because I used basically the one provided in the link, but if you need more info I will edit my question.
I finally found a solution to automatically update my application components reacting to language change.
A good tutorial can be found here; briefly you must find a way to notify your app that localized resource is changed.
public class LocalizedStrings : ViewModelBase
{
private static AppResources localizedresources = new AppResources();
public AppResources LocalizedResources
{
get { return localizedresources; }
}
public void UpdateLanguage()
{
localizedresources = new AppResources();
RaisePropertyChanged(() => LocalizedResources);
}
public static LocalizedStrings LocalizedStringsResource
{
get
{
return Application.Current.Resources["LocalizedStrings"]
as LocalizedStrings;
}
}
}
With this when user change language, you should simply run
LocalizedStrings.LocalizedStringsResource.UpdateLanguage();
and the job is done.

Resources