Trascina il controllo popup WPF
Domanda
il controllo Popup WPF è carino, ma un po 'limitato secondo me. c'è un modo per trascinare " un popup intorno quando viene aperto (come con il metodo DragMove () di Windows)?
questo può essere fatto senza grossi problemi o devo scrivere io stesso un sostituto della classe popup? grazie
Soluzione
Ecco una soluzione semplice che utilizza un pollice.
- Popup sottoclasse in XAML e codebehind
- Aggiungi un pollice con larghezza / altezza impostate su 0 (questo potrebbe essere fatto anche in XAML)
- Ascolta gli eventi MouseDown sul popup e genera lo stesso evento sul pollice
- Sposta popup su DragDelta
XAML:
<Popup x:Class="PopupTest.DraggablePopup" ...>
<Canvas x:Name="ContentCanvas">
</Canvas>
</Popup>
C #:
public partial class DraggablePopup : Popup
{
public DraggablePopup()
{
var thumb = new Thumb
{
Width = 0,
Height = 0,
};
ContentCanvas.Children.Add(thumb);
MouseDown += (sender, e) =>
{
thumb.RaiseEvent(e);
};
thumb.DragDelta += (sender, e) =>
{
HorizontalOffset += e.HorizontalChange;
VerticalOffset += e.VerticalChange;
};
}
}
Altri suggerimenti
Non è disponibile DragMove per PopUp. Solo una piccola soluzione, ci sono molti miglioramenti che puoi aggiungere a questo.
<Popup x:Name="pop" IsOpen="True" Height="200" Placement="AbsolutePoint" Width="200">
<Rectangle Stretch="Fill" Fill="Red"/>
</Popup>
Nel codice dietro, aggiungi questo evento mousemove
pop.MouseMove += new MouseEventHandler(pop_MouseMove);
void pop_MouseMove(object sender, MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
pop.PlacementRectangle = new Rect(new Point(e.GetPosition(this).X,
e.GetPosition(this).Y),new Point(200,200));
}
}
Un altro modo per raggiungere questo obiettivo è impostare il posizionamento del Popup su MousePoint. Questo fa apparire inizialmente il popup nella posizione del cursore del mouse.
Quindi puoi utilizzare un evento Thumb o MouseMove per impostare il popup orizzontale di Ampup & amp; VerticalOffset. Queste proprietà allontanano il Popup dalla sua posizione originale mentre l'utente lo trascina.
Ricorda di riportare a zero HorizontalOffset e VerticalOffset per il prossimo utilizzo del popup!
Il problema di perdere il mouse quando ci si sposta troppo velocemente potrebbe essere risolto
Questo è preso da msdn:
La nuova finestra contiene il contenuto secondario di Popup.
Il controllo popup mantiene un riferimento al suo contenuto secondario come figlio logico. Quando viene creata la nuova finestra, il contenuto di Popup diventa un figlio visivo della finestra e rimane il figlio logico di Popup. Al contrario, Popup rimane il genitore logico del suo contenuto secondario.
In altre parole, il figlio del popup viene visualizzato in una finestra autonoma.
Quindi, quando si tenta di quanto segue:
Popup.CaptureMouse ()
sta acquisendo la finestra del wrapper e non il popup stesso. Invece, usando Popup.Child.CaptureMouse ()
si acquisisce il pop-up effettivo.
E tutti gli altri eventi dovrebbero essere registrati usando Popup.Child
.
Come Popup.Child.MouseMove
, Popup.Child.LostCapture
e così via
Questo è stato testato e funziona perfettamente
Private Point startPoint;
private void Window_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
startPoint = e.GetPosition(null);
}
private void Window_MouseMove(object sender, MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
Point relative = e.GetPosition(null);
Point AbsolutePos = new Point(relative.X + this.Left, relative.Y + this.Top);
this.Top = AbsolutePos.Y - startPoint.Y;
this.Left = AbsolutePos.X - startPoint.X;
}
}
Funziona per trascinare la mia finestra, ma come mi è stato detto se sposterò il mouse velocemente, uscirebbe dalla finestra e smetterebbe di aumentare l'evento. Senza menzionare il trascinamento non è affatto liscio. Qualcuno sa come farlo correttamente, trascinamento piacevole e regolare, senza perderlo quando trascinato troppo velocemente ??? Pubblica un semplice esempio, se possibile, diverso da un intero tutorial che farebbe perdere il codice a principianti come me. Grazie!
Partendo dalla Jobi Joy , ho trovato una soluzione riutilizzabile che ti consente di aggiungere come controllo all'interno di xaml di una pagina / controllo esistente. Il che non è stato possibile aggiungere come Xaml con un nome poiché ha un ambito diverso.
[ContentProperty("Child")]
[DefaultEvent("Opened")]
[DefaultProperty("Child")]
[Localizability(LocalizationCategory.None)]
public class DraggablePopup : Popup
{
public DraggablePopup()
{
MouseDown += (sender, e) =>
{
Thumb.RaiseEvent(e);
};
Thumb.DragDelta += (sender, e) =>
{
HorizontalOffset += e.HorizontalChange;
VerticalOffset += e.VerticalChange;
};
}
/// <summary>
/// The original child added via Xaml
/// </summary>
public UIElement TrueChild { get; private set; }
public Thumb Thumb { get; private set; } = new Thumb
{
Width = 0,
Height = 0,
};
protected override void OnInitialized(EventArgs e)
{
base.OnInitialized(e);
TrueChild = Child;
var surrogateChild = new StackPanel();
RemoveLogicalChild(TrueChild);
surrogateChild.Children.Add(Thumb);
surrogateChild.Children.Add(TrueChild);
AddLogicalChild(surrogateChild);
Child = surrogateChild;
}
}