Archive

Archive for July, 2009

WPF Keyboard Focus

July 29th, 2009

imageJeg er ved at bygge et element til at liste alle mine media filer i mit MediaPlayerWPF, og en af de ting jeg rigtig gerne vil have er ordentlig keyboard controls og fokus (til hvis jeg skal bruge en Xbox Controller eller fjernbetjening til den fx.). Men keyboard fokus og fokus generelt i WPF kan være lidt irriterende!

Som vist i boksen til højre har jeg 2 listbokse, en der er bundet til kategorier, som hver har en liste af titler som den anden boks er bundet til.

Listerne bliver opdateret efter importeren er færdig med at læse mine harddiske. Det er meningen at den første liste skal få fokus så man kan bruge tastaturet til at navigere når listerne er færdig med at loade.

Der er et par problemstillinger med det jeg gerne vil opnå med denne control.

  • Det skal være naturligt at navigere mellem de 2 lister ved brug af tastaturet
  • Den venstre liste skal huske hvilket element der er selected så det er den der får fokus når man trykker venstre fra titel listen.
  • Kategori listen skal have fokus når den er loadet!

Jeg havde meget svært ved at opnå de første 2 krav. Det tog mig en evighed og alligevel var det den simpleste af alle løsninger. For Microsoft har allerede tænkt over det. På listboksene sætter man blot den Attached Property der hedder KeyboardNavigation.DirectionalNavigation til “Once". Dejligt simpelt og til at have med at gøre i forhold til alt det eventhandling jeg har været igennem for at prøve at efterligne det ;D

Det sidste problem tog mig også lidt tid at knuse. I første omgang var det ikke noget problem da jeg satte DataContext på min UserControl i constructoren, så kunne jeg blot vente på UserControl.Loaded og så sætte fokus til første element i listen med denne lille sag:

if (categoryList.Items.Count == 0)
    return;

if (categoryList.SelectedIndex < 0)
    categoryList.SelectedIndex = 0;

ListBoxItem lbi = categoryList.ItemContainerGenerator.ContainerFromIndex(categoryList.SelectedIndex) as ListBoxItem;
if (lbi != null)
{
    lbi.Focus();
    Keyboard.Focus(lbi);
}

Men! Da det godt kan tage lidt tid at importere fra diskene (specielt hvis de lige sover), så gør jeg det asynkront! Nu skal jeg jo så finde ud af hvornår jeg kan fokusere mit fine ListBoxItem. Det kan man ikke når datacontext bliver sat, når source bliver opdateret eller når min ObservableCollection der indeholder mine ViewModels bliver opdateret.

Man skal vente til UI’et er blevet genreret for alle ens elementer og det er såmænd også ItemContainerGenerator der står for det! Ved lige at lytte på hvornår den skifter Status vha. StatusChanged, kan man få lov til at fokusere det første element så snart listen har listbox items og ItemContainerGeneratoren har status GeneratorStatus.ContainersGenerated!

felizk Programming

NSIS Installer MSBuild Target

July 24th, 2009

Jeg var ved at blive træt af at zippe versioner af mine små programmer til Mads (min bror) og andre interesserede. Der gik altid koks i versionerne og kludder i hvor de skulle installerer.

Så jeg har lavet et lille MSBuild Target, der bygger en NSIS installer udfra indstillinger i ens csproj fil. Den bruger en (meget simpel) skabelon .NSI fil.

Target’et kræver selvfølgelig at man har installeret NSIS (gerne i $(ProgramFiles)\NSIS :D ).

Du kan hente kilden her: MSBUILD_NSIS.zip

felizk Programming