3 Stimmen

Abrufen der Form eines Steuerelements als Geometrie

Gibt es eine Möglichkeit, die Form eines Steuerelements zu erhalten und sie in eine Geometrie Objekt?

Ich habe die folgende Situation: In einer WPF-Anwendung wird ein Popup angezeigt. Dieses Popup ist kein Windows, es ist ein Steuerelement, das sichtbar wird. Der Rest der Anwendung wird dunkler als eine graue Schicht über der Anwendung ist.

Das Problem ist nun, dass diese graue Ebene auch über dem Popup selbst liegt, was durch das Design der Anwendung verursacht wird, und das Element, das angeklickt wurde und das Popup geöffnet hat, sollte auch nicht durch die Ebene verdeckt werden. Ich habe mich entschieden, eine Beschneidungsgeometrie an die graue Ebene anzuhängen, was in Ordnung ist, aber ich muss alle Formen und Pfade, die ich nicht ausblenden möchte, selbst erkennen.

Um also auf meine Frage zurückzukommen: Gibt es eine Möglichkeit, die Form eines Steuerelements zu erhalten und sie in eine Geometrie Objekt? Z.B. habe ich Wege gefunden, den VisualBrush eines Steuerelements zu erhalten, kann das aber auch nicht konvertieren - oder sehe einfach nicht, wie es möglich ist.

2voto

SvenG Punkte 5245

Können Sie es so machen: Entfernen Sie die Schaltfläche aus dem visuellen Baum und platzieren Sie sie auf dem Schmücker. Wenn die Verzierung geschlossen wird, fügen Sie sie wieder an das ursprüngliche übergeordnete Element an. Ich denke, dies ist viel flexibler als das Beschneiden von Geometrien und macht es viel flexibler (Sie könnten z. B. komplexe Inhalte wie Benutzersteuerelemente auf dem Zierelement platzieren).

Im folgenden Beispiel wird ein Panel als Container für die Schaltfläche verwendet.

Das Xaml (Fenster):

<Grid Margin="50" x:Name="myGrid" Background="LightBlue">
<Button x:Name="myButton" Width="80" Height="30" Click="myButton_Click">Show popup</Button>

Code dahinter: private FrameworkElementAdorner _adorner; private Panel _originalParent;

private void myButton_Click(object sender, RoutedEventArgs e)
{
  if (_adorner == null)
  {
    _adorner = new FrameworkElementAdorner(myGrid);
  }

  // remove the button from the parent panel and attach it to the adorner
  // otherwise remove from adorner and attach to original parent again
  if (_adorner.IsVisible)
  {
    AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(myGrid);
    adornerLayer.Remove(_adorner);

    Panel parent = VisualTreeHelper.GetParent(myButton) as Panel;
    if (parent != null)
    {
      parent.Children.Remove(myButton);
    }
    _originalParent.Children.Add(myButton);
  }
  else
  {
    _originalParent = VisualTreeHelper.GetParent(myButton) as Panel;
    if (_originalParent != null)
    {
      _originalParent.Children.Remove(myButton);
    }

    // Create the Adorner with the original button in it
    _adorner.Child = CreateAdornerContent(myButton);

    AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(myGrid);
    adornerLayer.Add(_adorner);
  }
}

/// <summary>
/// Creates some dummy content for the adorner
/// </summary>
private FrameworkElement CreateAdornerContent(Button myButton)
{
  Grid g = new Grid();
  g.Background = new SolidColorBrush(Colors.Yellow);

  TextBlock tb = new TextBlock();
  tb.Text = "I am the Adorner";

  g.Children.Add(tb);
  g.Children.Add(myButton);
  return g;
}

Und hier die einfache Verzierung, die nur ein frameworkElement anzeigt: class FrameworkElementAdorner : Adorner { private FrameworkElement _child;

public FrameworkElementAdorner(UIElement adornedElement)
  : base(adornedElement)
{
}

protected override int VisualChildrenCount
{
  get
  {
    return 1;
  }
}

protected override Visual GetVisualChild(int index)
{
  if (index != 0) throw new ArgumentOutOfRangeException();
  return _child;
}

public FrameworkElement Child
{
  get
  {
    return _child;
  }
  set
  {
    if (_child != null)
    {
      RemoveVisualChild(_child);
    }
    _child = value;
    if (_child != null)
    {
      AddVisualChild(_child);
    }
  }
}

protected override Size ArrangeOverride(Size finalSize)
{
  _child.Arrange(new Rect(new Point(0, 0), finalSize));
  return new Size(_child.ActualWidth, _child.ActualHeight);
}

}

Ich kann auch die vollständige sln hochladen, wenn Sie möchten. Ist das hier irgendwie möglich?

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X