Montag, 21. November 2011

Binding to the SelectedItems of ListBox using attached properties

In the last post I wrote about how to extend the ListBox to enable a DataBinding to the SelectedItems property.
It is not always possible to extend a control, so I took another look at the post by Marlon Grech where he uses a attached property to do the trick. I merged the two examples and resulted with a attached property that can handle a two way binding.

The only thing with this approach is that the collection, that the SelectedItems bind to, has to be created on initialization of the ViewModel

Here is the code to the attached property:
 public class ListBoxHelper  
 {  
    #region SelectedItems  
   
    ///  
    /// SelectedItems Attached Dependency Property  
    ///  
    public static readonly DependencyProperty SelectedItemsProperty =  
       DependencyProperty.RegisterAttached("SelectedItems", typeof (IList), 
                          typeof (ListBoxHelper),  
                          new FrameworkPropertyMetadata((IList) null,  
                                       new PropertyChangedCallback(OnSelectedItemsChanged)));  
   
    /// <summary>  
    /// Gets the SelectedItems property.  
    /// </summary>  
    /// <param name="d"></param>  
    /// <returns></returns>  
    public static IList GetSelectedItems(DependencyObject d)  
    {  
       return (IList) d.GetValue(SelectedItemsProperty);  
    }  
   
    /// <summary>  
    /// Sets the SelectedItems property.  
    /// </summary>  
    /// <param name="d"></param>  
    /// <param name="value"></param>  
    public static void SetSelectedItems(DependencyObject d, IList value)  
    {  
       d.SetValue(SelectedItemsProperty, value);  
    }  
   
    /// <summary>  
    /// Called when SelectedItems is set  
    /// </summary>  
    /// <param name="d"></param>  
    /// <param name="e"></param>  
    private static void OnSelectedItemsChanged(DependencyObject d, 
                                             DependencyPropertyChangedEventArgs e)  
    {  
       var listBox = (ListBox) d;  
       SetInternalSelectedItemsToPublic(listBox);  
       IList selectedItems = GetSelectedItems(listBox);  
   
       if (selectedItems is ObservableCollection<object>)  
       {  
          // if the list is a observable collection binde to the changed event 
          // to update the internal collection
          (selectedItems as ObservableCollection<object>).CollectionChanged += delegate  
                             {  
                                        SetSelectedDataItemsToInternal(listBox);  
                             };  
       }  
   
       listBox.SelectionChanged += delegate  
                      {  
                               SetInternalSelectedItemsToPublic(listBox);  
                      };  
    }  
   
   
    #region Implementation  
   
    static bool _isChanging;  
   
    private static void SetSelectedDataItemsToInternal(ListBox listBox)  
    {  
       if (_isChanging)  
          return;  
   
       _isChanging = true;  
   
       var selectedDataItems = GetSelectedItems(listBox);  
   
       if (listBox.SelectedItems != null)  
       {  
          listBox.SelectedItems.Clear();  
   
          if (selectedDataItems == null)  
          {  
             _isChanging = false;  
             return;  
          }  
   
          foreach (var item in selectedDataItems)  
             listBox.SelectedItems.Add(item);  
       }  
   
       _isChanging = false;  
    }  
   
    private static void SetInternalSelectedItemsToPublic(ListBox listBox)  
    {  
       if (_isChanging)  
          return;  
   
       _isChanging = true;  
   
       var selectedDataItems = GetSelectedItems(listBox);  
   
       if (selectedDataItems == null)  
       {  
          // the bound data type is not of typ IList / IList<object> / 
          // IEnumerable / Ienumerable<object>  
          // in this case the bound property has to be initialized first by the caller  
          _isChanging = false;  
          return;  
       }  
   
       selectedDataItems.Clear();  
   
       if (listBox.SelectedItems != null)  
       {  
          foreach (var item in listBox.SelectedItems)  
             selectedDataItems.Add(item);  
       }  
   
       _isChanging = false;  
    }  
         
    #endregion  
   
    #endregion  
 }  

And here is the XAML with the binding:
<ListBox ItemsSource="{Binding ListItems}" 
   c:ListBoxHelper.SelectedItems="{Binding SlectedListItems}" 
   SelectionMode="Multiple"/>

Sonntag, 20. November 2011

Binding to the SelectedItems of ListBox by extending the ListBox

A short while ago I needed to get access to the SelectedItems with DataBinding in my MVVM implementation. The SelectedItems property in the ListBox is read only and so there is no way to have a Binding to it. While searching for a solution I stumbled upon this post by Marlon Grech.
He explains how to create a bindable property for the SelectedItems using attached properties.

The problem with his example is that the binding only works one way when the user selects items in the ListBox. I needed to have a way where I could select items from the ViewModel as well.
The other thing was that I already had an extension of the ListBox.

So instead of creating an attached property I simply took the example and extended the ListBox with the SelectedDataItems property.

Here is the code to the extended ListBox
 public class ListBoxExt : ListBox  
 {  
    static ListBoxExt()  
    {  
       DefaultStyleKeyProperty.OverrideMetadata(typeof (ListBoxExt), 
           new FrameworkPropertyMetadata(typeof (ListBoxExt)));  
    }  
   
    protected override void OnSelectionChanged(SelectionChangedEventArgs e)  
    {  
       SetInternalSelectedItemsToPublic();  
   
       base.OnSelectionChanged(e);  
    }  
   
    #region SelectedDataItems  
   
    public static readonly DependencyProperty SelectedDataItemsProperty = 
       DependencyProperty.Register(  
       "SelectedDataItems",   
       typeof(IList),   
       typeof(ListBoxExt),  
       new FrameworkPropertyMetadata(  
          (IList) null,   
          FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,  
          new PropertyChangedCallback(OnSelectedDataItemsPropertyChangedCallback)));  
   
    /// <summary>  
    /// Gets an IList containing all selected items  
    /// </summary>  
    public IList SelectedDataItems  
    {  
       get  
       {  
          return (IList) GetValue(SelectedDataItemsProperty);  
       }  
       set  
       {  
          SetValue(SelectedDataItemsProperty, value);  
       }  
    }  
   
   
    /// <summary>  
    /// Handles changes to the SelectedDataItems property.  
    /// </summary>  
    private static void OnSelectedDataItemsPropertyChangedCallback(
            DependencyObject d, 
            DependencyPropertyChangedEventArgs e)  
    {  
       var listBox = d as ListBoxExt;  
       if (listBox == null)  
          return;  
   
       listBox.SetSelectedDataItemsCollection(e.NewValue as IList);  
    }  
   
    private void SetSelectedDataItemsCollection(IList selection)  
    {  
       if (_isChanging)  
          return;  
   
       SetSelectedDataItemsToInternal(selection);  
   
       if (selection != null && selection is ObservableCollection<object>)  
       {  
          // add a eventlistner to keep a two way binding  
          (selection as ObservableCollection<object>).CollectionChanged += 
                new System.Collections.Specialized.NotifyCollectionChangedEventHandler(
                                                BoundSelectedDataItemsCollectionChanged);  
       }  
    }  
   
    #region Implementation  
   
    bool _isChanging;  
   
    private void SetSelectedDataItemsToInternal(IList selectedDataItems)  
    {  
       if (_isChanging)  
          return;  
   
       _isChanging = true;  
   
       if (SelectedItems != null)  
       {  
          SelectedItems.Clear();  
   
          if (selectedDataItems == null)  
          {  
             _isChanging = false;  
             return;  
          }  
   
          foreach (var item in selectedDataItems)  
             SelectedItems.Add(item);  
       }  
   
       _isChanging = false;  
    }  
   
    private void SetInternalSelectedItemsToPublic()  
    {  
       if (_isChanging)  
          return;  
   
       _isChanging = true;  
   
       if (SelectedDataItems == null)  
       {  
          var selection = new ObservableCollection<object>();  
          selection.CollectionChanged += 
               new System.Collections.Specialized.NotifyCollectionChangedEventHandler(
                                              BoundSelectedDataItemsCollectionChanged);  
          SelectedDataItems = selection;  
       }  
   
       if (SelectedDataItems == null)  
       {  
          // the bound data type is not of typ IList / IList<object> / 
          // IEnumerable / Ienumerable<object>  
          // in this case the bound property has to be initialized first by the caller  
          _isChanging = false;  
          return;  
       }  
   
       SelectedDataItems.Clear();  
   
       if (base.SelectedItems != null)  
       {  
          foreach (var item in base.SelectedItems)  
             SelectedDataItems.Add(item);  
       }  
   
       _isChanging = false;  
    }  
   
    /// <summary>  
    /// gets executed when the bound collection is of type ObservableCollection 
    /// and the collection gets changed  
    /// </summary>  
    /// <param name="sender"></param>  
    /// <param name="e"></param>  
    void BoundSelectedDataItemsCollectionChanged(object sender, 
                        System.Collections.Specialized.NotifyCollectionChangedEventArgs e)  
    {  
       if (_isChanging)  
          return;  
   
       if (SelectedDataItems == null)  
          return;  
       SetSelectedDataItemsToInternal(SelectedDataItems);  
    }  
   
    #endregion  
   
    #endregion  
 }  


To be able to create a two way binding, the property for the SelectedDataItems has to be IList, IList<object>, IEnumerable or IEnumerable<object>. If a concrete type is used in the generic enumerations the binding will only work one way to the list.
Here is the XAML with the bindings:
<c:ListBoxExt ItemsSource="{Binding ListItems}" 
    SelectedDataItems="{Binding SlectedListItems}" 
    SelectionMode="Multiple"/>

Freitag, 18. November 2011

My first blog was refound

Today I just found my first blog at http://blog.uniface.ch/blogs/blog1.php

I was so amazed an happy about the refound blog, that I copied most posts to blogspot where I have all other blogs.

voodoo programming: n.


[from George Bush Sr.'s “voodoo economics”]

Link: Link: http://catb.org/~esr/jargon/html/V/voodoo-programming.html

1. The use by guess or cookbook of an obscure or hairy system, feature, or algorithm that one does not truly understand. The implication is that the technique may not work, and if it doesn't, one will never know why. Almost synonymous with black magic, except that black magic typically isn't documented and nobody understands it. Compare magic, deep magic, heavy wizardry, rain dance, cargo cult programming, wave a dead chicken, SCSI voodoo.

2. Things programmers do that they know shouldn't work but they try anyway, and which sometimes actually work, such as recompiling everything.

Alternativen zu XNA?


Ich hab mich gefragt was es eigentlich sonst noch so für Hilfsmittel zur GameProgrammierung gibt.
Als ich so am suchen war kahm mir die Idee!
Warum ein Framework benutzen wenn es ja sogar eine ganze Programmiersprache gibt die nur für das Programmieren von Games entwickelt wurde???

Mit Java von Sun sollte das ja auch gehen... Oder kann man Java noch für sonst was benutzen?

Jedenfalls habe ich mit NetBeans mal so ein Projekt für ein Natel-Game gestartet. Nach 2 1/2 Nächten coden hatte ich mein erstes Java Game fertiggestellt :D



Aber eine wirkliche Alternative zu XNA ist Java wirklich nicht. (Ist aber auch nur J2ME)
Die einfachsten sachen wie Formen (Rectangle usw) muss man sogar selber machen.
Es gibt aber auch einige gute sachen wie die Sprite Klasse. In dieser kann man viele Bildinformationen speichern. Allerdings gibts da mit XNA viel mächtigere Klassen wie Vector2 usw. Die GameCanvas und Graphics Klassen sind auch nicht schlecht allerdings auch kein Vergleich zu Game und dem SpriteBatch!

Und sowieso C# > Java... (ist halt von Microsoft...)

Jetzt muss ich nur noch schauen wie ich das Teil auf mein Natel beamen kann...

Update:
Das jar File kann man nur aufs Natel kopieren und von da aus installieren. Voll einfach :D

Ersten Glider meiner Flotte


Ich hab inzwischen wieder mal viel gemacht.
Zwei meiner ersten Glider sind fertig und 2 weiter folgen bald.


Hammerhead


Silverspear

Im Game habe ich eine komplett neue GameState Engine eingebaut. Ich hoffe bald mal was davon zeigen zu können.
Aber bis dahin habe ich noch einiges vor mir...

Da ich für mein SpaceGlider Game noch einige Raumschifflein brauche, habe ich mal Blender heruntergeladen und damit losgelegt.
Nach 5 Tagen experimentieren und herumklicken konnte ich mein erster 3D Glider erstellen (Allerdings nur als Bild in der draufsicht... Eigentlich brauche ich auch nicht mehr...).



Nicht schlecht für das erste mal oder? :-)
Nein ganz recht. Ich hab noch viel zu lernen.

Als mein Bruder gesehen hat was ich probiere hat er so schnell in 5 Minuten was hingezaubert...





LOL...

Der arbeitet aber auch in der 3D Branche :-)

Ich werde ihm aber sicher noch einige male über die Schulter schauen oder vieleicht sogar mal mit seinem 3DSMAX herumspielen. (Vieleicht ist das sooooo viel einfacher und daher konnte er es so schnell machen ;) )

Ich werde mal fleissig weiter an meinen GenFighters und MegaGenZerstörern arbeiten und diese dann auch hier der Öffentlichkeit presentieren.

Also stay tuned and behave

Das Radarsystem oder Wer hat Performance so brutal erschossen?


Mein Radarsystem ist dazu gedacht dass die Gegner mich (natürlich den Helden) nur dann angereiffen wenn ich in Sichtweite und in Reichweite bin.

Dazu habe ich ein ähnliches System gebaut wie bei der Pfadfindung. nur mit dem Unterschied dass keine h-Kosten entstehen(kosten bis zum Ziel). Somit wird im Kreis gesucht. Ich habe ein abbruchkriterium eingebaut das eintritt sobald eine Wand zwischen dem Endziel und dem Suchenden befindet.


Zwischendurch hatte ich allerdings ein kleines Stocken. Also habe ich einen Framecounter eingebaut. Dann kahm die Frage auf wieso dass der Framecounter nicht richtig Funktionierte???




Als ich dann die CPU auslastung anschaute wars dann klar dass er doch funktioniert...

Offt findet man den killer irgendwo versteckt. So wie es sich am Schluss herausstellte hat sich dieser aber gut gezeigt. Es lag einfach an allem... Der Berechnung, der Speicherung, dem Zeichnen...

So habe ich bis zu schluss alles umgebaut und Performance liebt mich wieder so wie früher :D





Erweiterung von A*


Ich habe meine A* Pfadfindung mit einer kleinen Schönheitskorektur erweitert. Ich habe alle Nodes eliminiert die nicht eine zwingende Richtungsänderung erfordern. Dadurch erhalten die beweglichen Figuren eine glattere Verlaufslinie.

Standard A*



Glattere Bewegung:



Die grünen Punkte sind die Nodes die ich direkt ansteuere.

Im Moment wird nur eine Linie beachtet. Es wird aber so Implementiert dass die ganze Fülle des Objekts beachtet wird. So wirds auch mit der Collision Detection was :-)

Diese Änderung bedeutet allerdings eine erhöhte Rechnerei beim erstellen des Pfades, da auf einer Geraden zwischen den 2 Tiles immer überprüft werden muss ob diese Gerade ein Unwalkable Tile berührt...

First steps mit Pathfinding

Wird mal zeit was zum Gamedesign zu sagen.

Ich bin gerade dabei im Bereich Gamedesign mit XNA ein wenig herum zu experimentieren.

Am schluss sollte ein 2D Space Shooter entstehen (allerdings auf Planeten und nicht wirklich im Weltall... Wird sich aber noch genauer zeigen...).

Da ich allerdings nicht über alles den Überblick behalten kann / will (was auch immer...) teste ich das ganze zerst Modular. Wenn die einzelnen Module richtig funzen werde ich diese in die Engine (Die Wicked GenEngin ;)) einbauen.

In diesem Teil möchte ich zeigen wie ich die Pfadfindung gemacht habe.

Zum starten habe ich mir mal überlegt wie das gehen muss damit eine Einheit iht Ziel finden kann. Das habe ich dann ziemlich aufwändig ausprogrammiert und getestet. Das Problem bei der Lösung war dass ich immer fast die ganze Map bis zum Ziel abgesucht habe.

Darauf hin habe ich mich im Internet schlau gemacht und hab mich in das magische A* eingelesen. Da wurde mein Fehler rasch sichtbar, da ich keine histerie + keine Kosten benutzt habe. Somit hatte ich so eine art Radar... (werde ich wahrscheinlich später auch noch benutzen können :D)
Somit habe ich meine Lösung zu einer A* umgebaut.

Als erstes braucht man eine Welt. Bei mir ists eine einfache Tile based map.



Bei jedem Spiel braucht man einen Helden.


Das Ziel ist


Der abgesuchte Pfad


Der definitive Pfad



So wird immer der kürzeste Pfad gesucht (halt A*).

Jetzt bin ich noch dran dass Nodes eliminiert werden bei denen keine umbedingte Richtungsänderung vorgenommen werden muss. So wird der Pfad viel schöner und direkter. Das ist aber nur möglich da die Bewegung meiner Figuren nicht auf die MapTiles begrenzt ist...

 Zu den nächsten Themen werde ich meine Pixel Collision Detection mit rotierenden Objekten aufzeigen und vieleicht noch was zu meinem Map generator. Vieleicht kommt sogar bald mal ein kleines Video B)