Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Community
  • |
  • Diskussionsforum
BringToFront() bei XAML/WPF?
xbredoillex
myCSharp.de - Member



Dabei seit:
Beiträge: 46

Themenstarter:

BringToFront() bei XAML/WPF?

beantworten | zitieren | melden

Hallo,

in dem im Anhang folgenden Codestück werden in einem Canvas zwei Figuren in jeweils einem ContentControl erzeugt, deren Größe und Position sich zur Laufzeit über Thumbs verändern lassen. Wenn man die Figuren übereinander schiebt ist immer die zuerst im Code erzeugte Figur im Vordergrund und überdeckt die andere.

Nun soll aber immer die gerade mit der Maus gepackte Figur im Vordergrund sein und beim Loslassen auch so verbleiben. BringToFront() gibt es ja nicht :) und irgendwie sitze ich mal wieder auf dem Schlauch.

Hat jemand einen Tip für mich?

Danke im voraus,
xbredoillex




ANHANG:

Die Code entstammt aus dem Projektordner "MoveResize" im Source-Download des Artikels http://www.codeproject.com/KB/WPF/WPFDiagramDesigner_Part1.aspx und kann dort direkt als Projekt gestartet werden.


<Window x:Class="DiagramDesigner.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:s="clr-namespace:DiagramDesigner"
        WindowStartupLocation="CenterScreen"
        Title="Move and resize"
        Height="550" Width="750">
  <Window.Resources>

    <!-- MoveThumb Template -->
    <ControlTemplate x:Key="MoveThumbTemplate" TargetType="{x:Type s:MoveThumb}">
      <Rectangle Fill="Transparent"/>
    </ControlTemplate>

    <!-- ResizeDecorator Template -->
    <ControlTemplate x:Key="ResizeDecoratorTemplate" TargetType="{x:Type Control}">
      <Grid>
        <s:ResizeThumb Height="3" Cursor="SizeNS" Margin="0 -4 0 0"
                       VerticalAlignment="Top" HorizontalAlignment="Stretch"/>
        <s:ResizeThumb Width="3" Cursor="SizeWE" Margin="-4 0 0 0"
                       VerticalAlignment="Stretch" HorizontalAlignment="Left"/>
        <s:ResizeThumb Width="3" Cursor="SizeWE" Margin="0 0 -4 0"
                       VerticalAlignment="Stretch" HorizontalAlignment="Right"/>
        <s:ResizeThumb Height="3" Cursor="SizeNS" Margin="0 0 0 -4"
                       VerticalAlignment="Bottom" HorizontalAlignment="Stretch"/>
        <s:ResizeThumb Width="7" Height="7" Cursor="SizeNWSE" Margin="-6 -6 0 0"
                       VerticalAlignment="Top" HorizontalAlignment="Left"/>
        <s:ResizeThumb Width="7" Height="7" Cursor="SizeNESW" Margin="0 -6 -6 0"
                       VerticalAlignment="Top" HorizontalAlignment="Right"/>
        <s:ResizeThumb Width="7" Height="7" Cursor="SizeNESW" Margin="-6 0 0 -6"
                       VerticalAlignment="Bottom" HorizontalAlignment="Left"/>
        <s:ResizeThumb Width="7" Height="7" Cursor="SizeNWSE" Margin="0 0 -6 -6"
                       VerticalAlignment="Bottom" HorizontalAlignment="Right"/>
      </Grid>
    </ControlTemplate>


    <!-- Designer Item Template-->
    <ControlTemplate x:Key="DesignerItemTemplate" TargetType="ContentControl">
      <Grid DataContext="{Binding RelativeSource={RelativeSource TemplatedParent}}">
        <s:MoveThumb Template="{StaticResource MoveThumbTemplate}" Cursor="SizeAll"/>
        <Control Template="{StaticResource ResizeDecoratorTemplate}"/>
        <ContentPresenter Content="{TemplateBinding ContentControl.Content}"/>
      </Grid>
    </ControlTemplate>

  </Window.Resources>

  <Canvas>
    <ContentControl Width="130"
                    MinWidth="50"
                    Height="130"
                    MinHeight="50"
                    Canvas.Top="150"
                    Canvas.Left="470"
                    Template="{StaticResource DesignerItemTemplate}">
      <Ellipse Fill="Red"
               IsHitTestVisible="False"/>
    </ContentControl>
    <ContentControl Width="130"
                    MinWidth="50"
                    Height="130"
                    MinHeight="50"
                    Canvas.Top="150"
                    Canvas.Left="150"
                    Template="{StaticResource DesignerItemTemplate}">
      <Path Fill="Blue"
            Data="M 0,5 5,0 10,5 5,10 Z"
            Stretch="Fill"
            IsHitTestVisible="False"/>
    </ContentControl>
  </Canvas>
</Window>



using System.Windows.Controls;
using System.Windows.Controls.Primitives;

namespace DiagramDesigner
{
    public class MoveThumb : Thumb
    {
        public MoveThumb()
        {
            DragDelta += new DragDeltaEventHandler(this.MoveThumb_DragDelta);
        }

        private void MoveThumb_DragDelta(object sender, DragDeltaEventArgs e)
        {
            Control designerItem = this.DataContext as Control;

            if (designerItem != null)
            {
                double left = Canvas.GetLeft(designerItem);
                double top = Canvas.GetTop(designerItem);
                Canvas.SetZIndex(designerItem, 0);
                Canvas.SetLeft(designerItem, left + e.HorizontalChange);
                Canvas.SetTop(designerItem, top + e.VerticalChange);
            }
        }
    }
}



using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;

namespace DiagramDesigner
{
    public class ResizeThumb : Thumb
    {
        public ResizeThumb()
        {
            DragDelta += new DragDeltaEventHandler(this.ResizeThumb_DragDelta);
        }

        private void ResizeThumb_DragDelta(object sender, DragDeltaEventArgs e)
        {
            Control designerItem = this.DataContext as Control;

            if (designerItem != null)
            {
                double deltaVertical, deltaHorizontal;
                Canvas.SetZIndex(designerItem, 0);

                switch (VerticalAlignment)
                {
                    case VerticalAlignment.Bottom:
                        deltaVertical = Math.Min(-e.VerticalChange, designerItem.ActualHeight - designerItem.MinHeight);
                        designerItem.Height -= deltaVertical;
                        break;
                    case VerticalAlignment.Top:
                        deltaVertical = Math.Min(e.VerticalChange, designerItem.ActualHeight - designerItem.MinHeight);
                        Canvas.SetTop(designerItem, Canvas.GetTop(designerItem) + deltaVertical);
                        designerItem.Height -= deltaVertical;
                        break;
                    default:
                        break;
                }

                switch (HorizontalAlignment)
                {
                    case HorizontalAlignment.Left:
                        deltaHorizontal = Math.Min(e.HorizontalChange, designerItem.ActualWidth - designerItem.MinWidth);
                        Canvas.SetLeft(designerItem, Canvas.GetLeft(designerItem) + deltaHorizontal);
                        designerItem.Width -= deltaHorizontal;
                        break;
                    case HorizontalAlignment.Right:
                        deltaHorizontal = Math.Min(-e.HorizontalChange, designerItem.ActualWidth - designerItem.MinWidth);
                        designerItem.Width -= deltaHorizontal;
                        break;
                    default:
                        break;
                }
            }

            e.Handled = true;
        }
    }
}
Dieser Beitrag wurde 2 mal editiert, zum letzten Mal von xbredoillex am .
private Nachricht | Beiträge des Benutzers
Levitas
myCSharp.de - Member



Dabei seit:
Beiträge: 95

beantworten | zitieren | melden

Versuchs mal mit dem ZIndex...

Sollte gehen mit:


Canvas.SetZIndex(highestControl, 1);

und für jedes andere nimmst du einfach


Canvas.SetZIndex(control, 0);

Mfg Marc
private Nachricht | Beiträge des Benutzers
xbredoillex
myCSharp.de - Member



Dabei seit:
Beiträge: 46

Themenstarter:

beantworten | zitieren | melden

Hi,

ich habe jetzt mit setZIndex() herumprobiert. Damit bringe ich das erste angeklickte Element in den Vordergrund. Leider geht das nur ein einziges mal beim allerersten angeklickten Objekt, dann verändert sich beim erneuten Bewegen eines Objektes die ZEbene nicht mehr.

Vermutlich, weil man beim setzen eines ZIndex immer die Indizes aller Objekte relativ dazu anpassen muss, sonst haben alle angeklickten irgendwann den gleichen ("obersten") Index. Kann das so stimmen?
Bei BringToFront()/SendToBack() ging das relative Setzen der Indizes automatisch.

Beim Versuch in MoveThumb_DragDelta() den ZIndex zu setzen kann man zwar den ZIndex des geklickten Objektes setzen, aber nicht den Index aller anderen anpassen. Innerhalb dieser Funktion bekommt man keinen Zugriff auf die anderen Elemente bzw. auf deren setZIndex-Funktion.

Das komplizierte Zugreifen auf die einzelnen verschachtelten Objekte macht es mir irgendwie unmöglich das Problem zu lösen, denn jede Schachtelebene hat völlig unterschiedliche Properties. Mal gibt es Parent/Child, mal nicht etc.
Ich habe es mit PreviewMouse-Events an verschiedenen Stellen versucht, da verheddere ich mich aber immer in den Schachtelebenen bzw. komme nicht weiter, weil ich die benötigten Objekte nicht erreichen kann.

Gibt es eine elegante Lösung, das mit Maus gegriffene Element immer in den Vordergrund zu bringen?

Gruß
xbredoillex
private Nachricht | Beiträge des Benutzers
Jéré
myCSharp.de - Member

Avatar #avatar-3137.png


Dabei seit:
Beiträge: 151

beantworten | zitieren | melden

Hi,


für deine Frage (ohne den ganzen Post gelesen zu haben) werden dir die Events MouseEnter und MouseLeave im Zusammenhang mit dem ZIndex hilfreich sein.
Dazu den ZIndex erhöhen und wieder runter setzen.

Grüßle
Jéré
private Nachricht | Beiträge des Benutzers
xbredoillex
myCSharp.de - Member



Dabei seit:
Beiträge: 46

Themenstarter:

beantworten | zitieren | melden

Hi,

danke für den Tipp, mit MouseEnter/Leave geht es jetzt halbwegs.

Sieht halt nicht so toll aus, wenn das aktuelle Objekt beim Loslassen wieder hinter einem anderen verschwindet. Es wäre schöner wenn die Ebenen in der Reihenfolge des Anklickens sortiert sind und nicht in der Reihenfolge in der sie erschaffen wurden.

Es scheint wirklich so, als müsste man den ZIndex aller Objekte selbst verwalten, wenn man das anständig umsetzen will.

Dazu müsste man aber auch den ZIndex des verdeckenden, nicht angeklickten Objekts ermitteln um die Werte der Indizes evtl. zu vertauschen.

Nur wie? Hat jemand eine Idee?

Gruß
xbredoillex


Hier der Code mit MouseEnter/Leave:


public class MoveThumb : Thumb
	{
        private int tempindex = 0;
        
        public MoveThumb()
	    {
            MouseEnter += new MouseEventHandler(MoveThumb_MouseEnter);
            MouseLeave += new MouseEventHandler(MoveThumb_MouseLeave);
	        DragDelta += new DragDeltaEventHandler(this.MoveThumb_DragDelta);
	    }

        private void MoveThumb_MouseEnter(object sender, MouseEventArgs e)
        {
            ContentControl item = this.DataContext as ContentControl;
            if (item != null)
            {
                tempindex = Canvas.GetZIndex((UIElement)this.DataContext);
                Canvas.SetZIndex((UIElement)this.DataContext, 99);
            }
        }

        private void MoveThumb_MouseLeave(object sender, MouseEventArgs e)
        {
            ContentControl item = this.DataContext as ContentControl;
            if (item != null)
            {
                Canvas.SetZIndex((UIElement)this.DataContext, tempindex);
            }
        }

	    private void MoveThumb_DragDelta(object sender, DragDeltaEventArgs e)
	    {
            Control item = this.DataContext as Control;
	        if (item != null)
	        {	
	            double left = Canvas.GetLeft(item);
	            double top = Canvas.GetTop(item);
				
	            Canvas.SetLeft(item, left + e.HorizontalChange);
	            Canvas.SetTop(item, top + e.VerticalChange);
	        }
	    }
	}
}
private Nachricht | Beiträge des Benutzers
dennisspohr
myCSharp.de - Member

Avatar #avatar-2982.jpg


Dabei seit:
Beiträge: 420
Herkunft: Westerwald

beantworten | zitieren | melden

Hallo xbredoillex,

hast du das Problem inzwischen lösen können? Ich habe das gleiche und benutze die selbe Bibliothek.

Grüße
Dennis
private Nachricht | Beiträge des Benutzers
winSharp93
myCSharp.de - Experte

Avatar #avatar-2918.png


Dabei seit:
Beiträge: 5.742
Herkunft: Stuttgart

beantworten | zitieren | melden

Hallo zusammen,

spontane Idee: Der MoveThumb könnte jeweils den letzten vergebenen Z-Index speichern und dann jedes Mal, wenn er aktiv wird, inkrementieren und zuweisen.
private Nachricht | Beiträge des Benutzers
xbredoillex
myCSharp.de - Member



Dabei seit:
Beiträge: 46

Themenstarter:

beantworten | zitieren | melden

Hallo dennisspohr,

eine richtige Lösung für das Problem habe ich nicht gefunden bzw. ab einem gewissen Punkt nicht weiter nachgeforscht.
Mein letzten gespeicherten Links zu dem Thema waren diese hier:

http://blog.norberteder.com/comments.php?y=07&m=11&entry=entry071119-164324
http://www.silverlightshow.net/items/Using-the-Canvas-control-in-Silverlight-2-Beta-1.aspx

Vielleicht hilft dir das ja weiter. Ich erinnere mich, dass ich das damals irgendwie umsetzen wollte.

Gruß
xbredoillex
private Nachricht | Beiträge des Benutzers