all of the bits and pieces
Archive for the ‘Development’ Category
Ten post chciałem napisać od czasu, gdy sprzedałem zawarty w nim pomysł Michałowi na jednym ze spotkań PG.NET w końcu się udało
Jeśli myślisz, że raz stworzysz schemat bazy danych dla swojej aplikacji i już nigdy go nie będziesz zmieniać to jesteś w błędzie. W czasie produkcji może się okazać, że coś zostało pominięte, coś można rozwiazać lepiej, jest błąd albo po prostu trzeba dodać nową funkcjonalność wymagającą zmian w schemacie.
Read the rest of this entry »
W Windows Vista(Installer 4.5) i Windows 7(installer 5.0) jest całkiem ciekawa funkcjonalność – buforowanie instalatorów msi. Rzecz całkiem przydatna, gdy niespecjalnie lubimy komunikaty w stylu “Nie można znaleźć pliku (ulubiony soft).msi”.
Read the rest of this entry »
Aktualizowanie aplikacji to moim zdaniem ważne zagadnienie. Bardzo często aplikacja podlega ciągłym zmianom, dodawane są nowe funkcjonalności, naprawiane błędy(oczywiście:) ). Istotne jest to, w jaki sposób taką aktualizację widzi użytkownik.
Read the rest of this entry »
Mono to otwarta implementacja środowiska .NET tworzona przez Novella – działa na linuxach i mac os.
Z ostatnich wiadomości: Microsoft obiecał, że nigdy nie będzie ścigał projektu mono o licencję, można przeczytać o tym na blogu Miguela, to może umocnić pozycję tego projektu, do tej pory niespecjalnie było wiadomo czy MSFT pozwie novella i zmusi do zamknięcia, więc raczej nie podchodziłem do projektu na 100% poważnie.
W Mono niestety nie uświadczysz WPF czy WCF, ale jest za to asp .net MVC. Jest też prawie 100% zgodność z Winsforms. Język C# jest w wersji 3.0 i obsługuje LINQ.
Dla Mono jest coś co się nazywa Mono Migration Analyzer (MoMA) – pozwala na sprawdzenie w jakim stopniu aplikacja będzie się uruchamiać na mono.
Wszystko fajnie, ale postanowiłem spróbować jak to wygląda w rzeczywistości na bardziej zaawansowanych aplikacjach. Wziąłem Smart Client Software Factory w wersji z kwietnia 2008, a konkretnie Quickstarts.BankTeller i przepuściłem przez MoMA, oto co dostałem:
Czyli w sumie nie jest źle! Dokładniejszy raport wygląda tak:
Pierwsza z uwag jest spowodowana tym, że w aplikacji jest wywoływana przeglądarka internerowa, której brakuje w Mono – co w sumie jest OK. Drugi brak już jest poważniejszy, ale z tego co kojarze jest w kolejce do zrobienia.
Czyli w sumie powinno się udać uruchomić aplikację w SCSF na linuxie – hmm to otwiera całkiem ciekawe możliwości. Teraz tylko muszę wybrać jakąś dystrybucję ( czy Polish Linux Distribution jeszcze żyje?) zainstalować na wirtualce i sprawdzić jak to działa w praktyce.
PS: Ostatnio pojawił się także ciekawy podcast Scotta Hanselmanna w tym temacie – do posłuchania tutaj.
O Iron pythonie czytałem już trochę wcześniej, jednak nie miałem okazji go faktycznie spróbować. Okazja na użycie pojawiała się jakiś czas temu – szukałem rozwiązania pozwalającego użytkowniokowi aplikacji mieć wpływ na pewne części aplikacji bez konieczności programowania, ani posiadania środowiska programistycznego. Iron Python nadał się do tego idealnie.
Leon Bambrick ma na swoim blogu świetny przykład:
W pierwszym polu tekstowym wpisujemy skrypt, który ma się wykonać po naciśnięciu GO. W skrypcie mamy dostęp do całego obiektu txt, który jest drugim polem edit – tutaj jest przykład pozwalący na zrobienie UpperCase z zaznaczonego tekstu. Całość można wywołać za pomocą prostych komend:
ScriptEngine engine = Python.CreateEngine();
ScriptScope scope = null;
scope = engine.CreateScope();
scope.SetVariable("txt", TargetTextBox);
string code = CommandTextBox.Text.Trim();
ScriptSource source = engine.CreateScriptSourceFromString(code, SourceCodeKind.Statements);
source.Execute(scope);
Jedyną wadą jest zauważalnie dłuższy czas pierwszego uruchomienia w stosunku do pozostałych. Trzeba pewnie będzie zrobić warmup podczas startu aplikacji.
IronPythona można pobrać z codeplex.
No i ciekawostka – instalator pythona jest napisany przy pomocy Windows Installer Xml.
No dobra, po godzinach też programuje, ale już dla przyjemności
dlatego nikt mi za to nie płaci
Sytuacja: gotowa aplikacja w ASP .NET MVC – język wszystkich komunikatów to angielski. Dodatkowo aplikacja nie była przystosowana w żaden sposób do lokalizacji. Można powiedzieć, że jest to typowa brownfield application.
Zadanie: spolszczyć całość aplikacji – zachowując przy tym możliwość pokazania interfejsu użytkownika w pierwotnej wersji językowej.
Pierwsze koty za płoty – rozwiązanie gorsze
Pierwsze rozwiązanie jakie przychodzi na myśl to – tłumaczenie wszystkich tekstów z kontrolerów i modyfikacja widoków. Sposób słaby i nie pozwoli na pokazanie interfejsu w oryginalnym języku.
Drugie rozwiązanie – lepsze
Kontrolery
Przeniesienie wszystkich stringów, które podlegają lokalizacji, z Controllerów do resourców w folderze App_LocalResources. Następnie trzeba stworzyć wersje resourców dla każdego języka.
Trzeba jeszcze wziąć pod uwagę, czy komunikaty są budowane za pomocą String.Format – w moim wypadku tak na szczęście było.
Wyciąganie stringów do resourców – to jest naprawdę mordercze zajęcie – na szczęście po małym wyszukiwaniu znalazłem super wtyczkę do Resharpera – RGreatEx. Wtyczka potrafi wyciągnąć stringi do resourców i w ich miejsce wstawić odpowiednie odwołania. Podobno potrafi także tłumaczyć za pomocą google translate, ale do automatycznego tłumaczenia jestem nastawiony sceptycznie.
Widoki
Zdublowanie plików widoków np About.aspx w wersji angielskiej –> About.pl.aspx w wersji polskiej. Wiem, teoretycznie powinienem też wyciągnąć wszystkie stringi do lokalizacji, jednak(odstawiając na bok różne dogmaty) takie rozwiązanie wydało mi się bardzie sensowne. No dobra, teraz tylko sposób żeby ViewEngine w pierwszej kolejności wyszukał stronę About.pl.aspx, a dopiero w drugiej About.aspx. Okazuje się, że najlepiej w tym celu zrobić własny ViewEngine:
public class LocalizationViewEngine : WebFormViewEngine
{
public LocalizationViewEngine() : base()
{
ViewLocationFormats = AppendCulture(ViewLocationFormats);
PartialViewLocationFormats = AppendCulture(PartialViewLocationFormats);
MasterLocationFormats = AppendCulture(MasterLocationFormats);
}
private string [] AppendCulture(string[] arr)
{
List<string> ret = new List<string>();
for (int i = 0; i < arr.Length; i++)
{
string s = arr[i];
s = s.Replace(".aspx",
"." + Thread.CurrentThread.CurrentUICulture.TwoLetterISOLanguageName + ".aspx");
s = s.Replace(".ascx",
"." + Thread.CurrentThread.CurrentUICulture.TwoLetterISOLanguageName + ".ascx");
s = s.Replace(".master",
"." + Thread.CurrentThread.CurrentUICulture.TwoLetterISOLanguageName + ".master");
ret.Insert(0, s);
}
ret.AddRange(arr);
return ret.ToArray();
}
Trzeba tylko jeszcze powiedzieć MVC, że używamy własnego silnika widoków w global.asax.cs:
ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new LocalizationViewEngine());
A w web.config zmienić ustawienia globalization:
<globalization
requestEncoding="utf-8"
responseEncoding="utf-8"
culture="en-US"
uiCulture="pl-PL"
/>
Teraz zostaje tylko nudna część tzn.: wygibasy lingwistyczne i tłumaczenie resource oraz widoków. Jak już jest wszystko wymyślone to średnio chce mi się odwalać czarną robotę ;P
Najbliższe spotkanie poznańskiej grupy .NET już w czwartek, 29 stycznia od godziny 18:00. Strona i rejestracja na spotkanie jest tutaj.
Modelowanie rzeczywistości w OSLO
Będziemy gościć Marcina Kruszyńskiego, który wystąpi z prelekcją pt "Modelowanie rzeczywistości w OSLO". Temat bardzo ciekawy i szczerze mówiąc wogóle mi nieznany. Wystąpienie Marcina będzie okazją do zapoznania się z tematem. Pozowoliłem sobie poszukać trochę materiałów na ten temat:
eXpress Persistent Objects na tle innych narzędzi ORM
Michał Korsak opowie o tym jak wygląda ORM ze stajni DevExpress na tle innych narzędzi ORM. To z kolei będzie okazja żeby podyskutować o ORM jak takich, także w świetle mojego poprzedniego posta dotyczącego entity framework.
Nadrabiając ostatnio zaległości w słuchaniu DotNetRocks w odcinku #411 o ORM-ach Ward Bell podniósł ciekawą kwestię, a mianowicie, że Entity Framework będzie dominującym mapperem obiektowo relacyjnym na rynku. Myśl całkiem przewrotna, szczególnie biorąc pod uwagę “Vote of No Confidence”(Alt.NET podcast – hej tutaj też Ward Bell) ze strony społeczności. Jednak warto odsunąć flamewar i love to hate relationship do MS na bok i spojrzeć na fakty.
Po pierwsze zasoby
Microsoft inwestuje w EF nieprawdopodobne zasoby, takie o których np.: NHibernate może tylko pomażyć. Oczywiście jak zwykle V1 pozostawia trochę do życzenia, ale MS już wielokrotnie dowiódł(patrz Vista –> Windows 7), że jednak potrafi się uczyć na błędach i słuchać klientów, więc następne wersje zapewne będą już o wiele lepsze.
Po drugie literatura
Ward podniósł też ciekawy argument – ile jest opublikowanych książek dotyczących NHibernate – okazuje się, że nie ma
natomiast już w tej chwili są dostępne conajmniej 3 książki na ten temat.Tutaj ciekawostka – link do bloga Julie Lerman, która sama jest autorką spoooorej książki o Entity Framework.
O EF na C2C
Julie Lerman będzie prelegentem na konferencji Communities2Communities więc będzie okazja, aby posłuchać o EF prosto z ust ekspertki. Na zeszłorocznej edycji C2C temat EF również był obecny pod postacią prelekcji Jarka Kowalskiego.
W viście są dosyć fajnie dopracowane kontrolki – to już wiecie. Moją szczególną uwagę zwróciły wizardy w aero, taki jak na przykład przy dodawaniu nowej drukarki:
To co głównie wyróżnia tego wizarda to przycisk wstecz w lewym górnym rogu i olbrzymi pasek tytułowy ( jak na mój gust nawet za duży).
Szukałem sposobu w jaki by można zrobić takiego wizarda we własnej aplikacji, który byłby zgodny z systemowym. Okazuje się, że istnieje nawet przykład, który pokazuje jak to zrobić w .NET, oczywiście jak zwykle w msdnie sprawa nie jest banalna i wpierw należy pobrać Vista Bridge Controls. Po skompilowaniu wszystkiego możemy zacząć używać fajnych aero wizardów w WPF:
Zrobienie czegoś takiego wymaga dosyć prostego xamla:
<v:AeroWizard x:Class="Wizard.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:v="clr-namespace:Microsoft.SDK.Samples.VistaBridge.Controls;assembly=VistaBridgeControls"
xmlns:l="clr-namespace:Wizard"
MainInstruction="AERO Wizard Test"
Title="Connect to a workplace"
>
<v:AeroWizard.Pages>
<Page>
<StackPanel>
<v:CommandLinkWPF Link="Choice One" Note="(Recommended)" Click="OnClick" />
<v:CommandLinkWPF Link="Choice Two" Note="(Not Recommended)" Click="OnClick" />
<v:CommandLinkWPF Link="Choice Three" Note="(Never Use)" />
</StackPanel>
</Page>
<Page>
<StackPanel>
<v:CommandLinkWPF Link="Some Other Link text" Note="This is a lot of descriptive text, which will enable the user to make a better choice." Click="OnClick" />
</StackPanel>
</Page>
</v:AeroWizard.Pages>
</v:AeroWizard>
Bardzo poważna wadą takiego rozwiązania to że będzie działać jedynie na Viście, na xp pojawi się komunikat o braku biblioteki dwmapi.dll. Żeby rozwiązać problem trzeba by napisać własną abstrakcję wizarda, która na viscie używałaby aero a na xp jakiegoś domyślnego wyglądu.
Microsoft some time ago published its Ribbon(known from Office 2007) control library for Windows Presentation Foundation. However it turns out that obtaining this library is quite burdensome:
- You have to go to a “Office UI Licensing” site and use “License the Office UI”, next you have to login with your Live Id and accept license agreement. Frankly I have no idea what have I agreed to
at the end you will be able to download WPFRibbonCTP, which contains ribbon control.
- I also strongly suggest to download Hands-On-Lab: What’s Coming in WPF:Datagrid, Ribbon and VSM which contains a great tutorial on how to use ribbon in your application. In exercise 2 there is a great app with ribbon which looks like this:
![image1[1] image1[1]](http://bartekszafko.pl/wp-content/uploads/2008/11/image11.png)
Using Ribbon in Prism
We had a talk on Prism on 12. Poznan .NET User Group Meeting. Szymon Kobalczyk gave a great talk on using Composite Application Library ( aka Prism ) to build great WPF applications. His presentation was very inspiring and gave me a kick-start into Prism. I decided to go on and use ribbon in prism. After some code reading it turned out that I just needed a custom RegionAdapter:
public class RibbonControlRegionAdapter : RegionAdapterBase<Ribbon>
{
private Ribbon m_regionTarget;
protected override void Adapt(IRegion region, Ribbon regionTarget)
{
m_regionTarget = regionTarget;
regionTarget.Tabs.Clear();
region.ActiveViews.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(OnActiveViewsChanged);
foreach ( RibbonTab v in region.ActiveViews)
regionTarget.Tabs.Add(v);
}
private void OnActiveViewsChanged(object sender, NotifyCollectionChangedEventArgs e)
{
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
foreach (RibbonTab v in e.NewItems)
m_regionTarget.Tabs.Add(v);
break;
case NotifyCollectionChangedAction.Remove:
foreach (RibbonTab v in e.NewItems)
m_regionTarget.Tabs.Remove(v);
break;
}
}
protected override IRegion CreateRegion()
{
return new AllActiveRegion();
}
}
Here is what shell aplication looks like before enabling a test module ( I know ugly, but it’s not the point:P ):

This is how shell application looks like after enabling module1:

Further development
In this example custom region adapter is built in such way that it only allows you to add whole new tabs to ribbon. You can image an adapter that does reparenting and allows you to add regions even in tabs itself or items to main menu.