Подтвердить что ты не робот

Как нарисовать окно в WPF (лучшая практика)?

Я пытаюсь написать небольшое интерактивное игровое приложение, где мне нужно иметь метод Draw, который будет рисоваться на экране, но не может понять, как структурировать метод для WPF.

Если это было Winforms, я мог бы использовать:

public void Draw (Graphics g)
{

}

Но для a WPF Window, что я должен иметь на нем в xaml (в настоящее время есть только Grid), и что должен этот метод Draw получать в качестве аргумента?

Сначала я хочу сделать это так, чтобы заставить его работать, тогда я могу подумать о том, как сделать его более WPF и т.д. Но теперь меня больше интересует, как это работает.

4b9b3361

Ответ 1

Как правило, вы "рисуете" в WPF совершенно другим способом.

В Windows Forms/GDI графический API является графическим API немедленного режима. Каждый раз, когда окно обновляется/отменяется, вы явно рисуете содержимое с помощью Graphics.

Однако в WPF все работает по-другому. Вы редко когда-либо прямо рисуете - вместо этого это графический API с сохраненным режимом. Вы указываете WPF, где хотите объекты, и он заботится о чертеже для вас.

Лучший способ подумать об этом - в Windows Forms вы бы сказали: "Нарисуйте линию от X1 до Y1. Затем нарисуйте строку от X2 до Y2. Затем...". И вы повторяете это каждый раз, когда вам нужно "перерисовать", поскольку экран недействителен.

В WPF вместо этого вы говорите: "Мне нужна строка от X1 до Y1. Мне нужна строка от X2 до Y2". Затем WPF решает, когда и как сделать это для вас.

Это делается путем размещения фигур на холсте, а затем позволяет WPF выполнять всю тяжелую работу.

Ответ 2

Когда слишком много объектов нужно нарисовать очень быстро (огромное Визуальное дерево), другой вариант будет использовать WriteableBitmap. Просто используйте свойство Pixels для установки пикселей и/или используйте метод Render для рисования UIElements.

Ответ 3

Я предпочитаю использовать метод OnRender, как в этом примере:

protected override void OnRender(DrawingContext drawingContext)
{
    base.OnRender(drawingContext);
     drawingContext.DrawRectangle(null, new Pen(Brushes.Black, 2), new Rect(0, 0, ActualWidth, Height));
}

Ответ 4

Чтобы реализовать поведение типа цикла Draw в WPF, вы можете использовать событие CompositionTarget.Rendering. Это повышается один раз за кадр, когда система рисования WPF выполняет рисование кадров.

Как отмечали другие, это не очень дружелюбный WPF, но он будет работать и может использоваться для получения более быстрого рисования из приложения WPF.

В большинстве случаев вы должны использовать один корневой холст и обновление, чтобы указать позицию Canvas элемента в событии CompositionTarget.Rendering.

Например, чтобы сделать эллипс по всему экрану, выполните следующие действия:

В вашем XAML (для окна размером от 640 до 480):

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

В вашем коде для окна, в котором находится вышеупомянутый XAML (убедитесь, что вы добавили ссылку на System.Windows.Media, чтобы увидеть объект 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);
    }