Autor Beitrag
IsNull
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 97
Erhaltene Danke: 11


VS 2010, C#, AHK
BeitragVerfasst: Sa 05.02.11 20:48 
Hallo,

Ich nutze folgendes Control um Map-Tiles anzuzeigen: greatmaps.codeplex.com. Meine Applikation folgt dem MVMV Pattern.
GMap.NET's GMapControl nutzt intern ein Canvas, um z.B. Map Marker darzustellen.

Mein Problem ist nun folgendes:
Schiebt man einen MapMarker (ist ein beliebiges UserControl) ausserhalb des sichtbaren Bereiches wird das wunderbar geclipt. Nun habe ich für die Marker einen Adorner definiert, um deren Selektionsstatus zu visualisieren - und diese Adorner werden nun quer über die gesammte Applikation gerendert. Sieht recht ulkig aus:

img812.imageshack.us...277/adornerissue.png

Ich hab mich zum Thema Adorner belesen, und die vermeintliche Lösung zum Problem ist einfach: Vom Marker wird der nächst höhere (Parent) AdornerLayer gesucht - und wenn ich meine Map mit einem <AdornerDecorator></AdornerDecorator> umschliesse sollte sich der Adorner nicht mehr auserhalb von diesem rendern lassen.
Das funktioniert nur leider nicht.

ausblenden XML-Daten
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
    <!-- DeliveryMapView -->
    <!-- Expects a set DataContext to a DeliveryMapViewModel Instance-->
    <Grid>
        <AdornerDecorator>
                <ContentControl ClipToBounds="True" Content="{Binding MapControl}">
                    <ContentControl.ContextMenu>
                        <ContextMenu>
                            <MenuItem Header="Add to Route" Command="{Binding AddSelectionToActiveRouteCommand}" />
                            <MenuItem Header="Remove from Route" Command="{Binding RemoveSelectionFromActiveRouteCommand}" />
                        </ContextMenu>
                    </ContentControl.ContextMenu>
                </ContentControl>
        </AdornerDecorator>
    </Grid>


Irgendjemand ne Idee was das sein könnte?

Abweichungen vom Standard:
Es gibt zwei Dinge, die von den 08/15 Beispielen abweichen:

Die Adorner definiere ich für gewöhnlich in xaml, mit diesen Klassen: www.codeproject.com/.../adornedcontrol.aspx
Grundsätzlich wird so das Control von einem AdornedControl : ContentControl umschlossen, und im Code davon passiert das unspektakuläre: this.adornerLayer = AdornerLayer.GetAdornerLayer(this);

GMap.Net ist leider nicht ganz MVVM freundlich, daher hat mein DeliveryMapViewModel ein Property MapControl was einer Instanz des GMap.NET GMapControls entspricht, und dieses binde ich dann wie oben zu sehen ist an den ContentControl.Content.

Grüsse
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Sa 05.02.11 21:32 
Ich habe noch nicht ganz den Überblick gewonnen, aber ob etwas auf dem richtigen AdornerLayer landet, solltest du leicht mit Suche bei Google SNOOP herausfinden können.

_________________
>λ=
IsNull Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 97
Erhaltene Danke: 11


VS 2010, C#, AHK
BeitragVerfasst: So 06.02.11 10:46 
Hallo Kha,

Danke für den Tipp mit Snoop - das hat folgendes zu Tage gefördert:
img132.imageshack.us...noopadornerissue.png

Wenn ich den Roten Rahmen richtig interpretiere, sollte der die Grenzen des AdornerLayers darstellen - genau dort sollte die Grenze auch sein. Aber die Adorners scheinen sich nicht darum zu kümmern, dass sie ausserhalb von diesem sind.

Lass mich wissen, was dir unklar ist an meinen Erläuterungen, ich versuche es dann besser zu umschreiben.
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: So 06.02.11 14:41 
Hm, da weiß ich ehrlich gesagt auch nicht weiter :nixweiss: . Nach einer kurzen Google-Suche scheint das Problem der meisten Leute zu sein, dass sich das Clipping von AdornerLayers gar nicht abschalten lässt :gruebel: .

_________________
>λ=
IsNull Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 97
Erhaltene Danke: 11


VS 2010, C#, AHK
BeitragVerfasst: Mo 07.02.11 09:45 
Ist mir auch aufgefallen dass die meisten über den AdornerLayer hinaus (teilweise sogar über das Fenster hinaus) ihre Adonrner Rendern wollen.

Nach einigen Tests hab ich es AFAIK raus. Ich habe das ganze in ein Testprojekt ausgelagert.

Aus dem hier (wo das clipping nicht funktioniert)
ausblenden XML-Daten
1:
2:
3:
        <Canvas ClipToBounds="True">
                    <!-- Items with Adorners -->
        </Canvas>


Habe ich das hier gemacht:
ausblenden XML-Daten
1:
2:
3:
4:
5:
6:
7:
        <Canvas ClipToBounds="True">
            <AdornerDecorator>
                <Canvas>
                    <!-- Items with Adorners -->
                </Canvas>
            </AdornerDecorator>
        </Canvas>

So clippen die Elemente korrekt.



Ich stehe nun leider noch vor der Herausforderung, diese verschachtelten Elemente in Code in das GMapsControl hineinzupatchen. Original sieht das ca so aus:

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
class GMapControl : ItemsControl, Interface
{
        public GMapControl() {
                var factoryPanel = new FrameworkElementFactory(typeof(Canvas));
                factoryPanel.SetValue(Canvas.IsItemsHostProperty, true);

                ItemsPanelTemplate template = new ItemsPanelTemplate();
                template.VisualTree = factoryPanel;
                ItemsPanel = template;


                Style st = new Style();
                {
                    st.Setters.Add(new Setter(Canvas.LeftProperty, new Binding("LocalPositionX")));
                    st.Setters.Add(new Setter(Canvas.TopProperty, new Binding("LocalPositionY")));
                    st.Setters.Add(new Setter(Canvas.ZIndexProperty, new Binding("ZIndex")));
                }
                ItemContainerStyle = st;

            // [...]
        }
// [...]
}


Meine Versuche hier ein AdornerDecorator sowie ein Child einzufügen sind mangels meiner Erfahrung was Templates im Codebehind angeht gescheitert. Hast du evtl einen Tipp wie ich hier den AdornerDecorator + Canvas noch reinschachteln kann?

Edit: Problem gelöst, Lösung folgt sogleich :)
IsNull Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 97
Erhaltene Danke: 11


VS 2010, C#, AHK
BeitragVerfasst: Mo 07.02.11 10:32 
Die Lösung des Problems ist ganz simpel. Hat man ein Items Control (egal was), und will dass dessen Adorner nicht darüberhinaus gerendert werden, muss man es wie bei msdn zu lesen erstmal mit einem AdornerDecorator umschliessen.

ausblenden XML-Daten
1:
2:
3:
4:
5:
            <AdornerDecorator>
                <Canvas>
                    <!-- Items with Adorners -->
                </Canvas>
            </AdornerDecorator>


Leider clippen die Element so immer noch nicht - ClipToBounds=True löst das:
ausblenden XML-Daten
1:
2:
3:
4:
5:
6:
 
            <AdornerDecorator ClipToBounds="True">
                <Canvas>
                    <!-- Items with Adorners -->
                </Canvas>
            </AdornerDecorator>


Edit: Vereinfacht.

Edit: Jetzt nerve ich mich gerade. Eigentlich offensichtlich, dass ClipToBounds nötig ist - obwohl in der msdn nie ein Wort darüber verloren wird. Naja ;)