Xamarin Forms SwipeListView

 

The running appLet’s see how to build a fully customizable and cross platform Swipe-Enabled ListView in Xamarin Forms.
[Download] You can download from my GitHub the working project. This article aims to show I solved the problem in order to let you build your own Xamarin Form component.

The starting idea

A SwipeListView is a ListView where you can swipe left or right to perform some actions.

ListViewTo achive our goal we would replace the content of every item into the ListView with three different Box called MainContent, SwipeLeftContent and SwipeRightContent. As you can imagine only the MainContent will be draggable. SwipeLeftContent and SwipeRightContent will be displayed depending on MainContent position.

As a Xamarin Forms developer you would try to build all the SwipeListView inside a PCL, but you will find that Xamarin Forms has some limits due to his cross-platform vocation.
At some point, for example, we would like to perform some pan operations but Xamarin Forms lacks of any decent gestures recognition functionality:

			var panRecognizer = new PanGestureRecognizer();
			panRecognizer.PanUpdated += (object sender, PanUpdatedEventArgs panEvent) {
				//All we have is panEvent.TotalX and panEvent.TotalY;
			}

We assume we have to create a native ViewCell, which means we may deal with a custom renderer. If you don’t know what a custom renderer is look at there: https://developer.xamarin.com/guides/xamarin-forms/custom-renderer/

Writing a ViewCell custom renderer (or, in other words, deriving from ViewCellRenderer) is more than what we need for now. I think that we should try to write all our design in a XAML PCL and use a custom renderer to manage gestures only.
So our Main.xaml would look like:

		<ListView ItemsSource="{Binding ListItems}">
			...<ViewCell>
				<xam:SwipeItemView BoundItem="{Binding .}">
					<xam:SwipeItemView.MainContent>
					<!-- Something bindable !-->
					</xam:SwipeItemView.MainContent>
				</xam:SwipeItemView>
			</ViewCell>...
		</ListView>

And we can expect a xam:SwipeItemView defined this way:

<ContentView>
	<Grid>
		<ContentView IsVisible="{Binding IsRightContentVisible}">
			<!-- Content showed when swiping right !--></ContentView>
		<ContentView IsVisible="{Binding !IsRightContentVisible}">
			<!-- Content showed when swiping right !--></ContentView>
		<ContentView>
			<ContentView x:Name="innerContent"><!--Default content !--></ContentView>
		</ContentView>
	</Grid>
</ContentView>

This object represents each list item object. I added this reference to make our component flexible: I wanted a fully customizable mainContent, which means a property which can contain a view with his own bindings.

The BindingContext is inherited inside all the hierarchy. You can imagine we don’t need a BoundItem object. But for our pourposes we need some internal binding inside our custom view in order to know if the user is swiping left or right (and than to choose which button have to be displayed).

The property IsRightContentVisible is the reason why we need a BoundObject:

namespace XamSwipeList.SwipeList
{
	public partial class SwipeItemView : ContentView, INotifyPropertyChanged
	{
		public bool SwipeCompleted { get; set; }
		public View MainContent { get ... set ... }
		public object BoundItem { get ... set ... }
		public static readonly BindableProperty MainContentProperty;
		public static readonly BindableProperty BoundItemProperty;
		public SwipeItemView()
		{...
			mainContent.BindingContext = this; //The important part
		}
		static SwipeItemView()
		{
			MainContentProperty = BindableProperty.Create(..., propertyChanged: MainContentChanged);
			BoundItemProperty = BindableProperty.Create(..., propertyChanged: BoundItemChanged);
		}

		private static void BoundItemChanged(BindableObject bindable, object oldValue, object newValue)
		{...
			(bindable as SwipeItemView).innerContent.BindingContext = newValue; //The important part
		...}

		private static void MainContentChanged(BindableObject bindable, object oldValue, object newValue)
		{...
			(bindable as SwipeItemView).innerContent.Content = (View)newValue;
		...}
	}
}

Dealing with the custom renderer

At this point we are going to write our custom renderers to manage Gestures and pass the swipe as a Translation for our View. Of course we have to override DispatchTouchEvent, but we will two problem.touchAreas

  • Our swipe action must start and ends inside the ViewCell or our swipe will be lost, because we can’t conserve touch outside the bounding box the the item which started the swipe (which is the one we want to swipe also if the swipe is completed outside his bounding box).
  • We will notice a second problem when we try to delete an Item from our ObservableCollection. Xamarin Forms has a bug that doesn’t allow you to properly remove an item. If you SwipeRight an item (changing his TranslationX property) in order to delete this item, the TranslationX property of the removed item will be applied to the next element. I reported this bug many times ago but nothing appened. To hardfix this bug we have to reset the TranslationX property before deleting the item. This bug is detailed on Xamarin Forms BugZilla

Because of those two problems, we have to create a new View, with his own CustomRenderer which inherits from ListView. This SwipeListView  will catch all the touch events fired inside the List.

namespace XamSwipeList.SwipeList
{
	public class SwipeListView : ListView
	{
		private List&lt;SwipeItemView&gt; TouchedElements;
		public void PreventXamarinBug()
		{
			foreach(var elem in TouchedElements)
			{
				elem.PristineItem();
			}
		}

		public void AppendTouchedElement(SwipeItemView item)
		{
			TouchedElements.Add(item);
		}
	}
}

Now, let’s see how the custom renderer works:

[assembly: Xamarin.Forms.ExportRenderer(...)]
namespace XamSwipeList.Droid.CustomRenderer
{
	class SwipeItemRenderer : ViewRenderer
	{
		public override bool DispatchTouchEvent(MotionEvent touch)
		{
			if(TouchDispatcher.TouchingView == null &amp;&amp; touch.ActionMasked == MotionEventActions.Down)
			{
				TouchDispatcher.TouchingView = this.Element;
				TouchDispatcher.StartingBiasX = touch.GetX();
				TouchDispatcher.StartingBiasY = touch.GetY();
				TouchDispatcher.InitialTouch = DateTime.Now;
				return true;
			} //TouchDispatcher should be a static class containing the swiping view
			return base.DispatchTouchEvent(touch);
		}
	}
}

We manage only the “first touch” on the ListItem‘s custom renderer. All the other actions will be managed into the SwipeList custom renderer:

[assembly: Xamarin.Forms.ExportRenderer(...)]
namespace XamSwipeList.Droid.CustomRenderer
{
	class SwipeListRenderer : ListViewRenderer
	{
		public override bool DispatchTouchEvent(MotionEvent touch)
		{
			if (TouchDispatcher.TouchingView != null)
			{
				double currentQuota = ((touch.GetX() - TouchDispatcher.StartingBiasX) / (double)this.Width); //swiping percent
				float x = touch.GetX();
				float y = touch.GetY();
				switch (touch.ActionMasked)
				{
					case MotionEventActions.Up:
						touchedElement.CompleteTranslation(currentQuota);
						this.Element.AppendTouchedElement(touchedElement);
						TouchDispatcher.ResetAll();
						break;
					case MotionEventActions.Move:
						TouchDispatcher.TouchingView.PerformTranslation(currentQuota);
						break;
				}
			}
			return base.DispatchTouchEvent(touch);
		}
	}
}

And this is it. The implementation of PerformTranslation() is trivial.

The real code

In this post I haven’t used working code for brevity and to focus on the logic of the implementation.

You can find the working project on my github here.

Contributors

I wrote the Android part only beacause I’m not confident with Xamarin iOs. Any contribution to this project on Github will be welcomed.
If you have any idea abount how to solve this Xamarin Forms bug, please send me a note. We all know Xamarin is young and buggy… but we can help fix these little issues.

Please, less code next year. My codemotion yearly experience.

I am not a conference reviewer or a professional blogger. I am only a developer who have participated at many Codemotion conferences in Italy during the last years. Last weekend I was in Milan to attend the Codemotion conference. It was a great event as I expected and I experiences many unique strength for this particular conference but also many weaknesses. This article is just a note for my thought.

My general thought about Codemotion

Maybe the thing I love the most is the presence of international companies with their stands. Two or three years ago, I discovered Azure on one of this – which now empowers almost all my projects. I had the opportunity to talk with real people working or promoting this technology. It is just an example to tell you I had the opportunity to look at their products and made my choice: I had the opportunity to meet the people – and not the website or documentation – who maintain those techs. I really love this human part. Collecting Twitter account and e-mail address is more that obtain free developer assistance; it is the right way to go deeper into one specific world.

The event would not exists without conferences. Both days were articulated in speeches of exactly forty minutes. For the talks I appreciated the most I think it is not enough (last year I attended a conference named “SQL or NoSQL” by Matteo Cartia – probably the most interesting talk I have ever been – for which 40 minutes was far too little). In this timespan, you will fast realize it is impossible to introduce a technology. You will not have the time to introduce nothing but a couple of key points and a small demo. However, I think that this bounded rush is a good trick to prevent most of boring talks. I would talk about those later on this post.

The food problem

Last but not least: the food. We need food. We are not spiritual entities. The portions was too small. Really, I do not know how they decided the menu for the conference – but as far as I know the lunch have to provide around the 35% calories needed in one day, which means 700kcal. We had a launch for children and the snacks machines became empty too fast. I was hungry all day long.

About Codemotion choices

Looking at the agenda, I realized that Codemotion have reduced during those years the space for business technologies. Codemotion is with no doubt the place who welcomes students and beginners the most. At the beginning of every talk, generally, a good speaker asks the audience to raise a hand if you already know what the conference is talking about or if you are friendly with one or more linked technologies. I saw that in all the JavaScript and Angular related talks the audience splits into exactly two parts: totally beginner and real developer. In contrast, high-quality talks (which are the minority) about big-data and business techs tent to attract the real-world developer.

Keeping this choice in mind, I may appreciate the lack of too high-level talks: Codemotion is not the place to master your skills. Anyway, I do not understand the serious lack of .NET technologies inside the event. I think Codemotion have to be braver while choosing their talk: it is easy to fit an audience with Angular but at what price? Where are the news? Is it possible that ASP.NET Core and the entire .NET Standard library are not covered at all at one of the most important event about coding in Italy?

Codemotion prefers Angular and JavaScript talks to all other techs due to its popularity I guess, but discovering that Codemotion is almost a conference for frontend developers was a bit sad for me. Obviously, this is not a complete truth: many underground backend and frontend technologies were represented but I noticed the precence of only three or four slots talking about .NET technologies.

Moreover, the talks about Xamarin, Roslyn and other high-level products (not necessarily .NET) were the only ones where I saw real programmers interested in a possible future use of a technology. Which is, I suppose, the primary objective of a talk. As you can imagine, beginners can appreciate those technologies too.

Except Angular, there were no coverage for largely used technologies in IT like .NET or Python or Java itself. I noticed a full coverage for only newborn trends, but not for the giants’ news. It is a shame to not spread these innovations to so many beginners. Codemotion is for many of them the only event they will participate. The only one opportunity they have to decide to become a programmer.

The code and slides problem

This year I saw the worst conference in my life. Will not tell the name, despite no one would read this article. The important thing is that this talk was a totally mistake. I am going to descript this particular talk just to introduce my thought about what makes a talk a good talk.

This particular talk was about Angular 2. I expected to hear something about what makes Angular 2 different from version 1.x and why I should take the effort to learn Typescript and the framework. Nothing of that. The talk started with almost two slide presenting Angular. The speaker said that Angular 2 improved performances and was completely rewritten, then she suggested us to move on Typescript. Period. After those two sentences, she moved on code. Code was everywhere and did not worked as expected. She injected into her project material design and I really did not know why. Why her demo had to be stylish? The presence of material design library forced her to implement dozens of html to present a card layout as you may imagine.

She finally coded a controller and a view doing basic thing like iterations and rest calls. The code, simple in itself, was not explained enough and although I think there were a problem with time and not with the competence of the speaker, the point of the session was not clear. Not for me and for many others in the room, as I heard. The big problem is that there were too much lines of code. The look and feel of the demo was too perfect at the expense of the code simplicity.

So, what am I trying to say with this example? Please: reduce your code lines to just one or two minimal examples. We are not you final app-users, so do not care about design. Prefer conceptual slides focused on the value of your talk in spite of the code.

The importance of no-code talks

Many talks was about some thread I really loved but the speakers was boring. This is a huge problem and in general the presentation of an idea is a problem for every developer. We cannot do everything. For this reason, I generally appreciate talks about business models, continuous budgeting and so on. As developers, we are used to navigate inside bad written API documentation, but we almost know nothing about the worlds of business and presentations.

For this reason, I encourage attendees to go to the talks, which are not about the code itself. They are the most helpful talks for me. In particular, I loved a talk called “public speaking for geeks” which aims to introduce you a world we have to manage but for which there is no API documentation.

The big deal of that talk, in particular, was in a simple element I wanted to mention. Lorenzo encourage you to “discover more”. How does he did it? He presented many links to other conferences, easy. Here is the “infinite knowledge”. The idea behind is that if you want to learn you have to walk with your legs and at Codemotion you would only receive some path to walk into.

As a developer, you have to participate to not coding talks to learn from the community and to improve your human skills, to meet people and share ideas. For the coding part, some links and a shot introduction will be enough, but Codemotion is a place to meet the people behind the scenes, a place to discover communities and introduce yourself into totally unknown things. At home you will surf the net and discover more.

Fondamenti di programmazione in Python per ingegneri

Cosa aspettarsi da questo articolo

Parto dal presupposto che, a mio avviso, chiunque lavori con i computer deve saper programmare almeno un minimo.
Scopo di questa mini-lezione non è formare grandi programmatori (io programmo da circa dieci anni e sono lontano anni luce da essere un grande programmatore) ma darvi le basi per poter scrivere un piccolo script.
Questa guida non si occupa di problemi di prestazioni e performance, problemi di scrittura e leggibilità del codice, teoria del codice e quant’altro. Vi fornisco solo elementi di utilizzo immediato: chi di voi diventerà “più esperto” e supererà questa mini-lezione probabilmente non utilizzerà mai più niente di tutto ciò che c’è scritto qui. Ma il fatto è che quanto state per imparare funziona e funziona subito. Livello di difficoltà prossima allo zero.
Ovviamente con le conoscenze qui sotto potrete al più scrivere dei piccoli script imperativi e nient’altro. Quanto basta per inserire “pezzi di codice” in programmi di uso comune per l’ingegneria.

Cosa significa scrivere un programma

Un programma è essenzialmente un insieme di istruzioni che il vostro computer riceve ed esegue. Linguaggi di programmazione “seri” hanno la possibilità di definire quale sia il punto d’ingresso del programma, in che tempo e con quali risorse devono essere eseguite le varie istruzioni e altre cose di questo tipo.

Un programma viene generalmente scritto in un editor di testo (anche il blocco note di windows) e poi passato ad un compilatore. Il compilatore ha il compito di convertire il vostro file (o insieme di file) in quello che definiamo bytecode. Cosa sia il bytecode se vi interessa ve lo cercate su internet, anche perchè è molto interessante sapere perché serve e quali vantaggi offre una “compilazione intermedia”… insomme, dovreste aver sentito la parola Java almeno una volta! Ma quello che conta sapere è che il vostro codice non viene eseguito dalla macchina così com’è, ma subisce prima alcune trasformazioni. In realtà una volta convertito in bytecode il vostro codice deve essere convertito in linguaggio macchina prima di poter essere realmente eseguito.

Noi ci occuperemo di illustrare in seguito i principi di base della cosiddetta programmazione imperativa, ovvero una forma di programmazione in cui essenzialmente si mettono in fila, disposte per riga, le diverse istruzioni che si vuole il computer esegua. Le istruzioni vengono compilate (ed eseguite) dall’alto verso il basso. In questo modo possiamo pensare l’intero codice come un unico algoritmo.

Giusto per incuriosirvi rispetto a qualcosa di cui non parleremo: la programmazione imperativa è oggi sostanzialmente abbandonata. Oggi si utilizzano paradigmi di programmazione assai diversi – il più diffuso è forse il paradigma OOP, in cui sostanzialmente si programma mettendo in risalto le qualità dei dati rispetto alle routine (Object Oriented Programming). Ma allora perchè fare una lezione sulla programmazione imperativa? Semplice: l’OOP è qualcosa di decisamente evoluto, che pone le sue basi sul concetto di astrazione dei tipi. Qualcosa che esula completamente dal nostro scopo e che richiederebbe troppo tempo.

La caratteristica dei programmi di cui tratteremo è:

  1. Tutto il codice è contenuto in un unico file
  2. Non viene fatto riferimento a stream, persistenza dei dati
  3. Non vengono presi in considerazione problemi di astrazione
  4. Non vengono fatti riferimenti a librerie esterne (quasi mai)

Il primo punto spiega un po’ la filosofia: vi voglio dare solo gli elementi che vi consentano di scrivere piccoli script da inserire dentro Dynamo o Rhyno… non ha senso spiegarvi come gestire progetti veri e propri. Non vi insegnerò neppure come salvare file o caricare dati esternamente. Anche se questo sarebbe interessante (per esempio ingrare un foglio Excel con Dynamo e Python non sarebbe male), ma richiede conoscenze più avanzate e un’approfondimento di concetti che non toccherò neppure. Altresì per l’astrazione, che essenzialmente mi imporrebbe di spiegare l’OOP o almeno le funzioni. Non vi spiegherò neppure come fare grafici o utilizzare strumenti scritti da terze parti, tranne il minimo indispensabile per utilizzare alcune funzioni matematiche di base (come seno e coseno).

Ok, iniziamo.

Python. Cos’è e primo avvio

Python è il linguaggio più semplice in assoluto. Possiamo dire che non ha neppure una vera grammatica, sostanzialmente scriverete esattamente quello che volete che il computer faccia.

A causa di questa semplicità e al fatto che defacto Python non viene neppure compilato (ma interpretato), Python viene utilizzato come linguaggio di programmazione per scriptare dentro molti programmi. E’ veloce e semplice. Questo vi basta.

Potete installare l’interprete Python (che a sua volta è scritto in linguaggio C) da qui: http://www.python.it/download/ – scegliete la versione 2.7 perchè su Dynamo in realtà quello che eseguirete non è Python ma IronPython (cosa cambia? a voi niente) che è basato sulla versione 2.7 di Python. Dico questo perchè sebbene quello che diremo in questa sede vale per tutte le versioni di Python, se deciderete di andare avanti è utile avere una versione perfettamente adatta ai vostri scopi.

In alternativa potete installare Canopy, che fornisce una versione di Python che include al suo interno numerose librerie che potrebbero esservi utili: https://www.enthought.com/products/canopy/

Ad installazione completata, se non ci sono intoppi troverete fra i vostri programmi “Idle”, che non è altro che una console Ppythonintroython JIT. Significa che voi scrivete del codice Python, premete invio, e questo viene eseguito. E’ lo step prima dello script. Tutta la prima parte di questo corso, per spiegare un po’ come funziona, sarà eseguita su Idle.

Ad esempio io ho scritto:

print("hello world")

e Python ha risposto “hello world”. Il comando print() produce la stampa dell’argomento.

Non fate caso alla mia versione di Python: voi scaricate la 2.7!

Fondamenti

Variabili

Provate a scrivere:

nome = "Cristiano"

e premete invio. Come vedete Python non stampa niente, ma ha memorizzato la stringa “Cristiano” dentro la variabile nome. Se ora digitate

print(nome)

otterrete la stampa del mio nome.
Altresì potete scrivere:

nome = "Cristiano"
print(nome) #Stampa: Cristiano
nome = "Filippo"
print(nome) #Stampa: Filippo
nome = "Mario"
nome = "Giulio"
print(nome) #Stampa: Giulio

Come vedete le istruzioni vengono eseguite dall’alto verso il basso, nell’ordine di scrittura.
Possiamo anche concatenare più stringhe:

nome = "Mario"
cognome = "Rossi"
print(nome + cognome) # MarioRossi
print(nome + " " + cognome) #Mario Rossi

Notate bene:

  1. Tutto ciò che segue il carattere # non viene considerato parte del codice, si tratta dunque di un commento del programmatore.
  2. I commenti e le stringhe devono essere su una linea singola
  3. Ogni linea deve contenere una sola istruzione
  4. Le stringhe devono essere contenute dentro le virgolette “”

Numeri

Potete immaginare facilmente come eseguire delle operazioni matematiche e quali “cose strane” possono capitare:

i = 5
j = 2
print(i+j) # 7
print(2*3) # 6
i = "5"
j = "2"
print(i+j) #stampa 52 (i e j vengono considerati stringhe: sono fra virgolette)
print(i*3) #stampa 555
print("ciao"*2) #stampa ciaociao

Liste (matrici)

Le variabili viste fino ad ora possono contenere solo un elemento per volta. Se le riassegnate perdete il valore precedente (abbiamo già visto degli esempi). E’ possibile creare e gestire una lista in questo modo:

mesi = [] #definisce una matrice
mesi.append("Gennaio") #aggiunge un primo elemento (indice 0)
mesi.append("Febbraio") #aggiunge un elemento in coda alla lista
mesi.append("marzo") #aggiunge un elemento in coda alla lista
mesi[2] = "Marzo" #modifica l'elemento con indice '2', cioè il terzo elemento
mesi.pop(2) #rimuove l'elemento con indice 2
mesi.append("Aprile")
mesi.insert(2, "Marzo") #inserisce marzo in terza posizione facendo scalare aprile in quarta

Vi ho mostrato 3 metodi dell’oggetto list.Un metodo è essenzialmente una funzione a cui accedete tramite l’operatore “.” che segue il nome di una variabile che fa riferimento ad un oggetto.

La tecnica del “.” fa riferimento al paradigma OOP (che non vedremo), vi basta sapere che per accedere alle funzionalità delle liste, create con [] dovete inserire il nome della variabile della lista seguita dal “.”. I metodi utilizzati sono:

  1. append(variabile) – aggiunge l’argomento alla lista (per valore)
  2. pop(index) – estrae dalla lista l’elemento numero index. se non impostate index, estrae l’ultimo inserito
  3. insert(index, var) – inserisce l’elemento in una posizione specifica

Questi tre sono i metodi base per le liste. Ovviamente ce ne sono molti di più, una ricerca su internet vi basterà per scoprirlo: https://developers.google.com/edu/python/lists

Altri metodi per istanziare e lavorare sulle liste

Potete provare anche istruzioni di questo tipo:

spesa = ["Carote", "Latte", "Miele"]
conteggio = len(spesa)
print(conteggio) #3
spesa.append("Biscotti")
conteggio2 = len(spesa)
print(conteggio) #3
print(conteggio2) #4

E’ anche possibile creare matrici di matrici ed eseguire operazioni su matrici:

vettore = [[[1],[0],[0]],[[0],[1],[0]],[[0],[0],[1]]]
mischio = ["mischio", "testo", "a", 3, "numeri"]
list1 = [1,2,3]
list2 = [4,5,6]
list1+list2 #[1,2,3,4,5,6]
sum(list1) #6

Insomma, spero di aver reso l’idea. Ulteriori metodi li trovare online. Basta cercare qualcosa come “intersezione liste con Python”, magari in inglese. Andate su Google e provate a cercare qualcosa come “how to intersect lists python” – troverete svariati post (in genere quelli che puntano sul sito stackoverflow forniscono risposte rapide ed attendibili).

Iterazioni

Il modo più semplice per iterare in una lista è illustrato in questo esempio. Digitate su Idle:

list = ["lunedì", "martedì", "mercoledì", "giovedì", "venerdì", "sabato", "domenica"]
for giorno in list:
	print("oggi è " + giorno)
print("Domani che giorno sarà?")

Come vedete la funzione print è indentata di un TAB dopo l’istruzione for. Questo comunica a Python che l’istrzione fa riferimento al blocco for, mentre “Domani che giorno sarà” no. Se non fosse presente il TAB, Python restituirebbe errore, infatti il blocco for richiede almeno un istruzione.
Notate la differenza scrivendo:

list = ["lunedì", "martedì", "mercoledì", "giovedì", "venerdì", "sabato", "domenica"]
for giorno in list:
	print("oggi è " + giorno)
	print("Domani che giorno sarà?")

Spiegazione del ciclo for

for è una parola riservata del Python. Nessuna variabile può chiamarsi in questo modo, in effetti “for” è una vera e propria istruzione. Il blocco for così come scritto indica che la variabile di iterazione “giorno” deve essere desunta dall’iterazione dentro la lista di nome “list”. La variabile “giorno” continua ad esistere anche fuori dal ciclo. Provate a scrivere:

print(giorno) #domenica

Questo comportamento può sembrarvi ovvio, in realtà non lo è e porta numerosi problemi (che non vedremo). Si dice, per chi volesse approfondire, che Python ha gestito globalmente lo “scope” della variabile.
Possiamo iterare in una lista anche per indice:

for i in range(0, len(list)):
	print(list[i])

Selezione (istruzione if)

Il costrutto if consente di eseguire una parte di codice solo se è vera la condizione del blocco if e alternativamente eseguirne un’altra. Ad esempio il codice seguente non produce nessun output

nome = "mario"
if nome == "cristiano":
	print("benvenuto")

La parola riservata else consente di inserire codice alternativo:

nome = "mario"
if nome == "cristiano":
	print("benvenuto")
else
	print("chi sei?")

Operatori booleani

Essenzialmente Python verifica il contenuto dell’istruzione contenuta in if, se vera esegue il blocco. Se è presente il blocco else e l’istruzione è falsa, viene eseguito questo.

Il blocco if viene eseguita se l’operatore restituisce il valore booleano True. I principi della logica booleana non fanno parte di questa lezione, ma pensate a “True” come “+” e “False” come “-” in matematica. Due “frasi” vere restituiscono vero, due frasi false restituiscono vero, una falsa e una vera, falso. Gli operatori di confronto sono:

  • a == b #vero se a è identico a b. Attenzione al doppio “=”. Il singolo “=” significa assegnazione.
  • a != b #vero se a è diverso da b
  • a < b, a > b, a<=b, a >= b #provate a immaginare…
  • Potete anche correlare più frasi con “and” o “or”

Quindi provate a digitare per esempio:

for giorno in list:
	print("Che bella giornata")
	if giorno != "Sabato" and giorno != "Domenica":
		print("Oggi ci si riposa")
	else:
		print("Oggi si lavora")
	print("... perchè oggi è " + giorno)

E adesso?

Questo ultimo programmino contiene tutti gli elementi che a mio avviso sono fondamentali.
Con queste informazioni ritengo possiate orientarvi e iniziare a scrivere qualche script per conto vostro. O aiutandovi con internet.

Sicuramente queste informazioni vi basteranno per iniziare a lavorare su Dynamo. Su YouTube ho caricato un video che utilizza Python per attraversare delle liste e selezionare determinati elementi: è un esempio pratico che vi consiglio di seguire per sostanziare quanto detto.

  • Questa non è una guida a Python, è solo un’introduzione. Io penso che chi vuole imparare questa roba possa facilmente farlo facendo due ricerche su internet e sbattendoci la testa sopra. Non avrei neppure il tempo per fare un maxi spiegone su Python. Peraltro spiegare i fondamentali è anche noioso e nei pochi articoli su questo blog mi sono concentrato su temi un po’ più interessanti e che un minimo invitano a ragionare… Diciamo che ho scritto questa paginetta per darvi gli strumenti per partire da soli 😉

Per i più temerari

  1. Un corso di Python di 13 ore online: https://www.codecademy.com/learn/python
  2. Il libro “Imparare Python” di Lutz è la base per imparare davvero a programmare in Python. Il libro costa una sessantina di euro, ma se volete essere dei pro, è l’inizio: https://www.amazon.it/Imparare-Python-Mark-Lutz/dp/8848125956/ref=sr_1_1?ie=UTF8&qid=1473362244&sr=8-1&keywords=imparare+python – una vola letto e appreso, il passo successivo sarà “Programmare Python”, sempre di Lutz. Questo secondo testo vi porterà a scrivere applicazioni più impegnative, magari anche piccoli giochi o programmi con una grafica decente.
  3. Python fornisce numerose librerie utili per numerosi scopi. Fra queste segnalo pyplot (qui: http://matplotlib.org/api/pyplot_api.html). Pyplot vi consente di stampare a video il grafico di qualsiasi funzione, provateci un po :). Ogni libreria è fornita di apposita documentazione che vi fornisce la descrizione dei vari comandi che potete eseguire. Prendete dimestichezza con queste “API” (Application Programming Interface) percé è il modo in cui i programmatori dicono ad altri programmatori come fare le cose. Ma attenzione: la vostra installazione di Python non andrà bene per questo scopo. Per usare Pyplot il modo più semplice sarà procurarsi Canopy: https://www.enthought.com/products/canopy/

Localizzare Data e Ora

Un tema con cui prima o poi qualsiasi progetto deve fare i conti è la gestione di date e orari, time-zone e “ore legali” varie. La dritta fondamentale numero uno è: salvate nel database solo date in formato UTC – questo perché solo in questo modo vi sarà possibile gestire conversioni e sconversioni.

Cosa serve

Nell’ipotesi di un’applicazione web, immaginiamo di avere diverse tabelle contenenti una campo “Time” che identifica l’ora in cui è stato effettuato l’inserimento della riga. Nell’ipotesi in cui fino ad oggi abbiamo stampato l’orario nel modo:

@item.Time.ToString()

Abbiamo bisogno di:

  • Verificare che tutti gli orari salvati sul DB siano del tipo UTC
  • Creare un modulo che consenta all’utente di scegliere la propria TimeZone
  • Modificare il modo in cui vengono stampate le diverse ore

Il primo problema si può risolvere anche con un semplice “Cerca e Sostituisci” per passare da DateTime.Now a DateTime.UtcNow.

Un Controller per selezionare il TimeZone

Ha senso immagazzinare il TimeZone scelto dall’utente nel DB piuttosto che in un cookie. Potete inserire una colonna nella della tabella degli utenti o creare una tabella a parte se dovete immagazzinare più dati specifici per la localizzazione (ad esempio valuta preferita, lingua, formato per le date…).
Potete ottenere l’elenco dei diversi TimeZone disponibili definendo una proprietà di sola lettura come questa:

		public static List<TimeZoneInfo> TimeZones { get
			{
				return TimeZoneInfo.GetSystemTimeZones().ToList<TimeZoneInfo>();
			}
		}

A questo punto potete stampare l’elenco generando una DropDownList. Nell’esempio qui sotto ipotizzo un Controller che espone un ViewModel con la proprietà “TimezoneId”, in cui devo inserire proprio il TimeZone scelto dall’utente.

@Html.DropDownListFor(m => m.TimezoneId, new SelectList(Config.TimeZones, "Id", "DisplayName"))

La procedura di salvataggio ovviamente dipende dal vostro progetto.

Visualizzazione dell’orario aggiornato

Piuttosto che scrivere un metodo in una classe apposita, io suggerisco di scrivere un Extension Method per l’oggetto DateTime. E’ importante segnalare al sistema che la data di ingresso sia del tipo UTC:

		public static DateTime Localize(this DateTime time)
		{
			time = DateTime.SpecifyKind(time, DateTimeKind.Utc);
			Account account = AgentAccount.Find(HttpContext.Current.User.Identity.Name);
			TimeZoneInfo tz = TimeZoneInfo.FindSystemTimeZoneById(account.TimeZone);
			DateTime t = TimeZoneInfo.ConvertTime(time, tz);
			return t;
		}

Nell’esempio sopra ho ipotizzato una classe “Account” che mappa la tabella degli utenti.
Ora per stampare l’orario corretto sarà sufficiente:

@item.Time.Localize().ToString()