Как нарисовать окно в WPF (лучшая практика)?
Я пытаюсь написать небольшое интерактивное игровое приложение, где мне нужно иметь метод Draw
, который будет рисоваться на экране, но не может понять, как структурировать метод для WPF.
Если это было Winforms
, я мог бы использовать:
public void Draw (Graphics g)
{
}
Но для a WPF Window
, что я должен иметь на нем в xaml (в настоящее время есть только Grid
), и что должен этот метод Draw
получать в качестве аргумента?
Сначала я хочу сделать это так, чтобы заставить его работать, тогда я могу подумать о том, как сделать его более WPF
и т.д. Но теперь меня больше интересует, как это работает.
Ответы
Ответ 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);
}
Ответ 5
Yow должен добавить холст (или изменить сетку для холста), а затем нарисовать его. Здесь Microsoft tut при рисовании поверх холста
Кроме того, я не знаю, как связанный этот другой вопрос с вашим, но вы можете проверить его.