Вопрос или проблема
Изначально проблема заключалась в вопросе “Как обновить элементы UI из другого класса?”, которую я решил с помощью
public static MainWindow window
{
get
{
return Application.Current.Windows.OfType<MainWindow>().FirstOrDefault();
}
}
используя строку типа “MainWindow.window.(элемент ui для обновления);” для обновления элемента UI
Я решил попробовать добавить страницы в свое приложение, что я и сделал с помощью
public MainWindow()
{
AssemblerGUI assemblerWindow = new AssemblerGUI();
NavigationFrame.Navigate(assemblerWindow);
}
(NavigationFrame – это название элемента Frame в xaml)
Страницы работают, но вышеуказанное решение, позволяющее другим классам изменять UI, не работает и выбрасывает “Ссылка на объект не задана для объекта экземпляра” каждый раз, когда оно вызывается, из-за того, что страница создается для перехода к ней в фрейме.
Я догадался, что мог бы просто поместить весь код в файл .xaml.cs страницы, но это было бы довольно раздражающе для меня в будущем, когда я буду добавлять функции.
Я попробовал свое предыдущее решение, но оно выбрасывает ошибку, когда страница создается (и должна создаваться для работы XAML)
public static AssemblerGUI page
{
get
{
return Application.Current.Windows.OfType<AssemblerGUI>().FirstOrDefault();
}
}
Ответ или решение
Да, обновление элементов пользовательского интерфейса (UI) из другого класса в WPF возможно, но требует использования правильного подхода для обеспечения связи между классами и актуальным состоянием UI. Ваш первоначальный метод, использующий статическое свойство для доступа к окну, не будет работать в случае с навигацией за пределами основного окна в новую страницу. Давайте рассмотрим более подходящий способ.
Подход с использованием событий и делегатов
- Создание событий в вашей странице: Создайте событие на странице, которое будет вызываться, когда необходимо обновить UI. Это позволит другим классам подписаться на это событие и получать уведомления.
public partial class AssemblerGUI : Page
{
// Событие для обновления UI
public event EventHandler<string> UpdateUiRequested;
public AssemblerGUI()
{
InitializeComponent();
// Подписка на событие, если это необходимо
UpdateUiRequested += OnUpdateUiRequested;
}
private void OnUpdateUiRequested(object sender, string message)
{
// Обновите ваш UI элемент здесь
myTextBox.Text = message;
}
public void RequestUpdateUI(string message)
{
UpdateUiRequested?.Invoke(this, message);
}
}
- Использование события в другом классе: В вашем другом классе вы можете получить доступ к экземпляру
AssemblerGUI
, и по мере необходимости вызывать методRequestUpdateUI
.
public class SomeOtherClass
{
private AssemblerGUI assemblerPage;
public SomeOtherClass(AssemblerGUI page)
{
assemblerPage = page;
}
public void UpdateAssemblerPage()
{
// Запрос на обновление UI
assemblerPage.RequestUpdateUI("Обновленное сообщение");
}
}
- Передача экземпляра страницы между классами: Убедитесь, что вы передаете экземпляр страницы, когда создаете другой класс. Например, в вашем
MainWindow
:
public MainWindow()
{
InitializeComponent();
AssemblerGUI assemblerWindow = new AssemblerGUI();
NavigationFrame.Navigate(assemblerWindow);
// Создание другого класса и передача экземпляра страницы
SomeOtherClass otherClass = new SomeOtherClass(assemblerWindow);
otherClass.UpdateAssemblerPage(); // Пример вызова обновления
}
Другие рекомендации
-
MVVM Паттерн: Подумайте о применении паттерна MVVM (Model-View-ViewModel), который в WPF является стандартом. Этот подход разъединяет логику приложения и UI, позволяя следить за изменениями через через
INotifyPropertyChanged
. -
Основной поток UI: WPF требует, чтобы все изменения UI происходили в основном потоке интерфейса. Если вы вызываете ваши методы из фоновых потоков, убедитесь, что вы вызываете их на UI-потоке.
Используя эти методы, вы сможете организовать обновление UI из разных классов более чисто и не нарушая принципы проектирования. Это также значительно упростит добавление новых функций в будущем.