Comment dessiner sur une fenêtre dans WPF (best practice)?

J'essaie d'écrire une petite application interactive de type jeu, où j'ai besoin d'une méthode Draw qui va dessiner à l'écran, mais qui ne peut pas comprendre comment structurer la méthode pour WPF.

Si c'était Winforms, je pourrais utiliser:

public void Draw (Graphics g)
{

}

Mais pour un WPF Window, Que devrais-je avoir dans le xaml (actuellement seulement un Grid), et que devrait recevoir cette méthode Draw comme argument?

D'abord, je veux le faire comme ça pour le faire fonctionner, alors je peux penser à la façon de faire il plus WPF, etc. Mais maintenant, je suis plus intéressé à faire fonctionner cela.

22
demandé sur Joan Venge 2011-04-07 22:46:47

5 réponses

Typiquement, vous "dessinez" dans WPF d'une manière complètement différente.

Dans Windows Forms / GDI, l'API graphique est une API graphique en mode immédiat. Chaque fois que la fenêtre est actualisée/invalidée, vous dessinez explicitement le contenu à l'aide de graphiques.

Dans WPF, cependant, les choses fonctionnent différemment. Vous dessinez rarement directement - à la place, c'est une API graphique en mode conservé. Vous dites à WPF où vous voulez les objets, et il s'occupe du dessin pour vous.

La meilleure façon de penser de celui-ci, dans Windows Forms, vous diriez "tracez une ligne de X1 à Y1. Puis tracez une ligne de X2 à Y2. Puis ...". Et vous répétez cela chaque fois que vous avez besoin de "redessiner" puisque l'écran est invalidé.

Dans WPF, à la place, vous dites "je veux une ligne de X1 à Y1. Je veux une ligne de X2 à Y2."WPF décide alors quand et comment le dessiner pour vous.

Ceci est fait en plaçant les formes sur un canevas, puis en laissant WPF faire tout le travail dur.

17
répondu Reed Copsey 2011-04-07 18:53:54

Quand il y a juste trop d'objets à dessiner très rapidement (énorme arbre visuel) une autre option serait d'utiliser un WriteableBitmap. Utilisez simplement la propriété Pixels pour définir les pixels et / ou utilisez la méthode Render pour dessiner UIElements.

7
répondu Erno de Weerd 2011-04-07 19:08:29

Je préfère utiliser la méthode OnRender comme dans cet exemple:

protected override void OnRender(DrawingContext drawingContext)
{
    base.OnRender(drawingContext);
     drawingContext.DrawRectangle(null, new Pen(Brushes.Black, 2), new Rect(0, 0, ActualWidth, Height));
}
5
répondu Marek Kwiendacz 2011-04-07 18:53:23

Pour implémenter un comportement de type de Boucle De Tirage dans WPF, vous pouvez utiliser CompositionTarget.Rendu événement. Ceci est soulevé une fois par image lorsque le système de dessin WPF peint des cadres.

Comme d'autres l'ont souligné, ce N'est pas très convivial pour WPF, mais cela fonctionnera et peut être utilisé pour obtenir un comportement de dessin plus immédiat d'une application WPF.

Dans la plupart des cas, vous utiliseriez un canevas racine unique et mettriez à jour la position du canevas d'un élément sur CompositionTarget.Rendu événement.

Par exemple, pour faire voler une ellipse sur tout l'écran, Faites ceci:

Dans votre XAML (pour une fenêtre de taille 640 par 480):

<Canvas x:Name="theCanvas">
    <Ellipse x:Name="theEllipse" Height="10" Width="10" Fill="Black" />     
</Canvas>

Dans votre Code derrière pour la fenêtre dans laquelle se trouve le XAML ci-dessus (assurez-vous d'ajouter une référence au système.Windows.Pour voir L'objet CompsitionTarget:

    public static Random rand = new Random();
    public View()
    {
        InitializeComponent();
        CompositionTarget.Rendering += CompositionTarget_Rendering;
    }

    void CompositionTarget_Rendering(object sender, System.EventArgs e)
    {
        double newLeft = rand.Next(0, 640);
        double newTop = rand.Next(0, 480);

        theEllipse.SetValue(Canvas.LeftProperty,newLeft);
        theEllipse.SetValue(Canvas.TopProperty, newTop);
    }
2
répondu Brad Cunningham 2011-04-07 19:30:19

Yow devrait ajouter une toile (ou changer la grille pour une toile), puis dessiner dessus. Voici Microsoft tut sur le dessin sur une toile

Aussi, je ne sais pas à quel point cette autre question est liée à la vôtre, mais vous voudrez peut-être la vérifier.

1
répondu felixmm 2017-05-23 10:30:59