Страницы

Поиск по вопросам

суббота, 23 марта 2019 г.

Создание шаблона окна в WPF

В WinForms можно было сделать окно с элементами. Потом создать еще одно окно, унаследованное от первого и добавить на него еще элементы. Как в WPF делает такое? Что-то у меня не выходит такое провернуть.


Ответ

Это можно сделать, но довольно сложно, и требует известной технической квалификации.
Давайте рассмотрим пример, где нужно сделать окно с дополнительным текстовым сообщением снизу.
Для начала, вам нужно унаследоваться от класса Window
[TemplatePart(Name = "PART_MessageCountHost", Type = typeof(Panel))] // будет объяснено позже class WindowWithMessage : Window {
и определить переопределение метаданных, чтобы стили, определённые в ResourceDictionary без ключа, подхватывались:
static WindowWithMessage() { DefaultStyleKeyProperty.OverrideMetadata( typeof(WindowWithMessage), new FrameworkPropertyMetadata(typeof(WindowWithMessage))); }
Затем, вам нужен сам текст как свойство окна:
#region dp string MessageText public string MessageText { get { return (string)GetValue(MessageTextProperty); } set { SetValue(MessageTextProperty, value); } }
public static readonly DependencyProperty MessageTextProperty = DependencyProperty.Register( "MessageText", typeof(string), typeof(WindowWithMessage), new UIPropertyMetadata(OnMessageChanged)); #endregion
При изменении MessageText будет вызываться OnMessageChanged
В принципе, нам не особенно нужно знать, где именно будет показываться — это, в конце-концов, вопрос стиля/темплейта. Но предположим, что нам нужна кастомная логика: мы хотим считать, сколько раз message менялся.
int messageCount = 0;
static void OnMessageChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { WindowWithMessage self = (WindowWithMessage)d; self.messageCount++; self.UpdateMessageCount(); }
Для этого нам нужно знать, где это отображать. Для этого нам нужно попросить темплейты, чтобы они сообщали нам нужную информацию. Для этого используем объявление TemplatePart перед классом (см. выше).
Panel messageCountHost;
Визуальный элемент для счётчика сообщений может меняться только при применении темплейта.
public override void OnApplyTemplate() { base.OnApplyTemplate(); messageCountHost = GetTemplateChild("PART_MessageCountHost") as Panel; UpdateMessageCount(); }
void UpdateButtons() { if (messageCountHost == null) return;
messageCountHost.Children.Clear();
var textControl = new TextBlock() { Text = messageCount.ToString() };
messageCountHost.Children.Add(textControl); }
}
Окей, это был lookless control. Теперь для него нужно написать визуальную часть.
Для этого вы должны в корне своего проекта создать подкаталог Themes, и в нём ResourceDictionary Generic.xaml. Названия важны, не меняйте их. Если такой файл уже есть, просто добавьте в него стиль.

Теперь можно использовать новое окно как обычно:

Комментариев нет:

Отправить комментарий