QLPreviewController in Monotouch - xamarin.ios

I want to open PDF files using QLPreviewController in Monotouch, but I can't to do this.
QLPreviewItem is an abstract class, but object of this type returns method :
QLPreviewControllerDataSource.GetPreviewItem(QLPreviewController, int)
Anybody has worked example of QLPreviewController in Monotouch?

subclass QLPreviewItem, and then return
object from GetPreviewItem:
public class QlItem : QLPreviewItem
{
string title;
Uri uri;
public QlItem (string title, Uri uri)
{
this.title = title;
this.uri = uri;
}
public override string ItemTitle {
get { return title; }
}
public override NSUrl ItemUrl {
get { return uri; }
}
}

At least on Cocoa Touch, it is sufficient to return an NSURL object in the data source method (QLPreviewControllerDataSource.GetPreviewItem() on mono touch - previewController: previewItemAtIndex: on cocoa touch).
NSURL already implements QLPreviewItem. So unless you want to do fancy stuff, you don't need to subclass/implement QLPreviewItem.

Related

C# Class implementation with generics

Hi everyone I am studying C# but ran into some compiler errors:
I am getting the error: 'LinkedList' does not implement interface member 'IEnumerable.GetEnumerator()'
I think I did.
Below is the code:
using System;
using System.Collections.Generic;
namespace LinkedListGenericsExample
{
public class LinkedListNode<T>
{
//constructor
public LinkedListNode(T value)
{
//code here
}
//code here
}
//LinkedList class with generics. It inherit the IEnumerable class with
//generics. Should I use IEnumerable or IEnumerable<T>?
public class LinkedList<T>: IEnumerable<T>
{
//code here
}
public LinkedListNode<T> AddLast(T node)
{
//code here
}
public IEnumerator<T> GetEnumerator()
{
//code here
}
//here I think the GetEnumerator() method is implemented
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
//Trying this but not working. Also I am confused.
/*
IEnumerator IEnumerable<T>.GetEnumerator()
{
return GetEnumerator();
}
*/
//Main() below
}
I am using the Visual Studio Code to compile the code.
Error ecountered:
'LinkedList' does not implement interface member 'IEnumerable.GetEnumerator()'
Using the generic type 'IEnumerator' requires 1 type arguments
Using the generic type 'IEnumerable' requreis 1 type arguments
'IEnumerable' in explicit interface declaration is not an interface
Question:
1) Should I inherit the IEnumerable class or IEnumerable class with generic?
2) How can I implement the "IEnumerable.GetEnumerator()" It looks like the compiler is not recognized my GetEnumerator() implementation but I am not sure why....
Need some help here. Thank you!
Updating the complete code below. It works!!
using System;
using System.Collections; //using System.Collections instead
namespace LinkedListGenericsExample
{
//Linked list node class in Generics form
public class LinkedListNode<T>
{
//LinkedListNode constructor
public LinkedListNode(T value)
{
this.Value = value;
}
public T Value;
public LinkedListNode<T> Next {get; internal set;}
public LinkedListNode<T> Prev {get; internal set;}
}
public class LinkedList<T>: IEnumerable
{
public LinkedListNode<T> First {get; private set;}
public LinkedListNode<T> Last {get; private set;}
public LinkedListNode<T> AddLast(T node)
{
var newNode = new LinkedListNode<T>(node);
if (First == null)
{
First = newNode;
Last = First;
}
else
{
Last.Next = newNode;
Last = newNode;
}
return newNode;
}
public IEnumerator GetEnumerator()
{
LinkedListNode<T> current = First;
while(current != null)
{
yield return current.Value;
current = current.Next;
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
/*
IEnumerator IEnumerable<T>.GetEnumerator()
{
}
*/
}
class Program
{
static void Main(string[] args)
{
//Console.WriteLine("Hello World!");
var list2 = new LinkedList<int>();
var list3 = new LinkedList<String>();
list2.AddLast(1);
list2.AddLast(3);
list2.AddLast(5);
//Go throuhg entire list of numbers
foreach(int i in list2)
{
Console.WriteLine(i);
}
Console.WriteLine();
list3.AddLast("2");
list3.AddLast("four");
list3.AddLast("foo");
//Go through entire list of strings
foreach(string s in list3)
{
Console.WriteLine(s);
}
}
}
}
Regarding your two questions, here are 2 cents.
1. I would suggest you implement the generic version. This would ensure type-safety and other benefits. You can read more on advantages of generics in this link. . Since you are learning C#, it would be a good idea to read about it.
Your implementation looks good.Please add reference to System.Collections namespace to your code for fixing the compile errors.
using System.Collections;

ASP.NET using UrlHelper in ViewModel

I'm trying to strongly type (such as it is) some URLs for a web app when I build a viewmodel.
So I have something like:
new MyModel {
Text = "Foo",
Url = new UrlHelper(Request.RequestContext).Action("MyAction")
}
This works just fine in a controller method, but I have another situation where I am not receiving the Request.Context because it's being called in another class.
Is there another way to do this so that I'm not using "magic strings" and/or relying on the context object?
Use Reference
HttpContext.Current
which is derived from system.web. There for following code will work anywhere in your application.
UrlHelper objUrlHelper = new UrlHelper(HttpContext.Current.Request.RequestContext);
objUrlHelper.Action("About");
Example:
public class MyViewModel
{
public int ID { get; private set; }
public string Link
{
get
{
UrlHelper objUrlHelper = new UrlHelper(HttpContext.Current.Request.RequestContext);
return objUrlHelper.Action("YourAction", "YourController", new { id = this.ID });
}
}
public MyViewModel(int id)
{
this.ID = id;
}
}

Xamarin CollectionViewCell not instantiating from storyboard

I am collaborating with a designer who styles elements on my Xamarin project storyboard. I have trouble referencing his carefully placed elements in code. All the outlets are created, but in a UICollectionViewCell the UILabels etc are not instantiated. Here is code from a simple test app to demonstrate the problem.
The Xamarin generated code-behind:
[Register ("CardCell")]
partial class CardCell
{
[Outlet]
[GeneratedCode ("iOS Designer", "1.0")]
UILabel txtName { get; set; }
void ReleaseDesignerOutlets ()
{
if (txtName != null) {
txtName.Dispose ();
txtName = null;
}
}
}
My attempt to set the UI properties which causes the crash:
public partial class CardCell : UICollectionViewCell
{
public CardCell (IntPtr handle) : base (handle)
{
}
public void Update(string name)
{
txtName.Text = name; // throws exception here, because textName is null
}
}
The view controller with delegate methods:
public partial class TestCollectionController : UICollectionViewController
{
static NSString cardCellId = new NSString ("cardcell");
string[] cards = new string[] {"Red", "Green", "White", "Blue", "Pink", "Yellow"};
public TestCollectionController (IntPtr handle) : base (handle)
{
}
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
CollectionView.RegisterClassForCell (typeof(CardCell), cardCellId);
}
public override nint NumberOfSections (UICollectionView collectionView)
{
return 1;
}
public override nint GetItemsCount (UICollectionView collectionView, nint section)
{
return (nint)cards.Length;
}
public override UICollectionViewCell GetCell (UICollectionView collectionView, NSIndexPath indexPath)
{
CardCell cell = (CardCell)collectionView.DequeueReusableCell (cardCellId, indexPath);
var card = cards [indexPath.Row];
cell.Update(card);
return cell;
}
}
I have tried both the Xamarin iOS Designer and Xcode's Interface Builder, but it does not make a difference. Any help will be greatly appreciated.
Examples of collection views driven by a storyboard are quite scarce, but I found this one and teased through it meticulously till I discovered that it did not include the call to register a class for the cell. So, remove this line:
CollectionView.RegisterClassForCell (typeof(CardCell), cardCellId);
and suddenly everything works as expected.
I was following this recipe and other examples, which all had the call included, which is only needed when you don't use a storyboard.

How is IClock resolved with SystemClock in this example?

I am trying to learn IOC principle from this screencast
Inversion of Control from First Principles - Top Gear Style
I tried do as per screencast but i get an error while AutomaticFactory try create an object of AutoCue. AutoCue class has contructor which takes IClock and not SystemClock. But my question is , in screencast IClock is resolved with SystemClock while inside AutomaticFactory .But in my code , IClock does not get resolved . Am i missing something ?
class Program
{
static void Main(string[] args)
{
//var clarkson = new Clarkson(new AutoCue(new SystemClock()), new Megaphone());
//var clarkson = ClarksonFactory.SpawnOne();
var clarkson = (Clarkson)AutomaticFactory.GetOne(typeof(Clarkson));
clarkson.SaySomething();
Console.Read();
}
}
public class AutomaticFactory
{
public static object GetOne(Type type)
{
var constructor = type.GetConstructors().Single();
var parameters = constructor.GetParameters();
if (!parameters.Any()) return Activator.CreateInstance(type);
var args = new List<object>();
foreach(var parameter in parameters)
{
var arg = GetOne(parameter.ParameterType);
args.Add(arg);
}
var result = Activator.CreateInstance(type, args.ToArray());
return result;
}
}
public class Clarkson
{
private readonly AutoCue _autocue;
private readonly Megaphone _megaphone;
public Clarkson(AutoCue autocue,Megaphone megaphone)
{
_autocue = autocue;
_megaphone =megaphone;
}
public void SaySomething()
{
var message = _autocue.GetCue();
_megaphone.Shout(message);
}
}
public class Megaphone
{
public void Shout(string message)
{
Console.WriteLine(message);
}
}
public interface IClock
{
DateTime Now { get; }
}
public class SystemClock : IClock
{
public DateTime Now { get { return DateTime.Now; } }
}
public class AutoCue
{
private readonly IClock _clock;
public AutoCue(IClock clock)
{
_clock = clock;
}
public string GetCue()
{
DateTime now = _clock.Now;
if (now.DayOfWeek == DayOfWeek.Sunday)
{
return "Its a sunday!";
}
else
{
return "I have to work!";
}
}
}
What you basically implemented is a small IoC container that is able to auto-wire object graphs. But your implementation is only able to create object graphs of concrete objects. This makes your code violate the Dependency Inversion Principle.
What's missing from the implementation is some sort of Register method that tells your AutomaticFactory that when confronted with an abstraction, it should resolve the registered implementation. That could look as follows:
private static readonly Dictionary<Type, Type> registrations =
new Dictionary<Type, Type>();
public static void Register<TService, TImplementation>()
where TImplementation : class, TService
where TService : class
{
registrations.Add(typeof(TService), typeof(TImplementation));
}
No you will have to do an adjustment to the GetOne method as well. You can add the following code at the start of the GetOne method:
if (registrations.ContainsKey(type))
{
type = registrations[type];
}
That will ensure that if the supplied type is registered in the AutomaticFactory as TService, the mapped TImplementation will be used and the factory will continue using this implementation as the type to build up.
This does mean however that you now have to explicitly register the mapping between IClock and SystemClock (which is a quite natural thing to do if you're working with an IoC container). You must make this mapping before the first instance is resolved from the AutomaticFactory. So you should add the following line to to the beginning of the Main method:
AutomaticFactory.Register<IClock, SystemClock>();

JAXB use String as it is

I use REST and i was wondering if i can tell jaxb to insert a string field "as-it-is" into the outgoing xml.
Certainly i count unpack it before returning, but i would like to save this step.
#XmlRootElement(name="unnestedResponse")
public class Response{
#Insert annotation here ;-)
private String alreadyXml;
private int otherDate; ...
}
Is there a possability to tell JAXB to just use the String as it is without escapting? I want that the client does not have to parse my response and then parse this field.
greetings,
m
You can use the #XmlAnyElement and specify a DomHandler to keep a portion of the XML document as a String.
Customer
import javax.xml.bind.annotation.*;
#XmlRootElement
public class Customer {
private String bio;
#XmlAnyElement(BioHandler.class)
public String getBio() {
return bio;
}
public void setBio(String bio) {
this.bio = bio;
}
}
BioHandler
import java.io.*;
import javax.xml.bind.ValidationEventHandler;
import javax.xml.bind.annotation.DomHandler;
import javax.xml.transform.Source;
import javax.xml.transform.stream.*;
public class BioHandler implements DomHandler<String, StreamResult> {
private static final String BIO_START_TAG = "<bio>";
private static final String BIO_END_TAG = "</bio>";
private StringWriter xmlWriter = new StringWriter();
public StreamResult createUnmarshaller(ValidationEventHandler errorHandler) {
return new StreamResult(xmlWriter);
}
public String getElement(StreamResult rt) {
String xml = rt.getWriter().toString();
int beginIndex = xml.indexOf(BIO_START_TAG) + BIO_START_TAG.length();
int endIndex = xml.indexOf(BIO_END_TAG);
return xml.substring(beginIndex, endIndex);
}
public Source marshal(String n, ValidationEventHandler errorHandler) {
try {
String xml = BIO_START_TAG + n.trim() + BIO_END_TAG;
StringReader xmlReader = new StringReader(xml);
return new StreamSource(xmlReader);
} catch(Exception e) {
throw new RuntimeException(e);
}
}
}
For More Information
http://blog.bdoughan.com/2011/04/xmlanyelement-and-non-dom-properties.html
Following bdoughan's answer did not work for me as I encountered errors during marshalling when the text contained the '& character (e.g. in URLs or when using HTML entities such as e.g. " ").
I was able to resolve this by changing the custom DomHandler's marshal method to
public Source marshal(String et, ValidationEventHandler veh) {
Node node = new SimpleTextNode(et);
return new DOMSource(node);
}
where SimpleTextNode implements the Node interface as follows:
class SimpleTextNode implements Node {
String nodeValue = "";
#Override
public SimpleTextNode(String nodeValue) {
this.nodeValue = nodeValue;
}
#Override
public short getNodeType() {
return TEXT_NODE;
}
// the remaining methods of the Node interface are not needed during marshalling
// you can just use the code template of your IDE...
...
}
PS: I would have loved to leave this as a comment to bdoughan's answer, but unfortunately I have way too little reputation :-(

Resources