Обновите данные родительского окна из дочернего окна. С# WPF

Есть родительское окно, в нем объявлена ​​страница, на странице есть кнопка (Редактировать). По нажатию на кнопку откроется окно, после его закрытия данные в родительском окне должны обновиться.

Родительское окно ViewModel

public class MasterWinViewModel : Notify
{
    private object _curentPage;

    public object CurentPage
    {
        get { return _curentPage; }
        set
        {
            _curentPage = value;
            SignalChanged("CurentPage");
        }
    }

    public UserApi ProfileUser
    { 
        get => profileUser;
        set 
        {
            profileUser = value;
            SignalChanged("ProfileUser");
        } 
    }
    public CustomCommand Main { get; set; }
    public CustomCommand Help { get; set; }
    public CustomCommand Search { get; set; }
    public CustomCommand MyMediaLibrary { get; set; }
    public CustomCommand Profile { get; set; }
    public CustomCommand Test { get; set; }

    private UserApi profileUser;

    public MasterWinViewModel()
    {

        Task.Run(GetUserId);

       


        Test = new CustomCommand(() =>
        {
            Test nn = new Test();
            nn.Show();
        });

        Main = new CustomCommand(() =>
        {
            CurentPage = new MainPage();
            SignalChanged("CurentPage");
        });

        Help = new CustomCommand(() =>
        {
            CurentPage = new HelpPage();
            SignalChanged("CurentPage");
        });

        Search = new CustomCommand(() =>
        {
            CurentPage = new SearchPage();
            SignalChanged("CurentPage");
        });

        MyMediaLibrary = new CustomCommand(() =>
        {
            CurentPage = new MyMediaLibraryPage();
            SignalChanged("CurentPage");
        });

        Profile = new CustomCommand(() =>
        {
            CurentPage = new ProfilePage();
            SignalChanged("CurentPage");
        });
    }

    public async Task GetUserId()
    {
        Task.Delay(200).Wait();
        var t = SingInWindowViewModel.UsId;
        var result = await Api.GetAsync<UserApi>(t, "User");
        ProfileUser = result;
        SignalChanged("ProfileUser");
    }
   
    

}

Страницы ViewModel

public class ProfilePageViewModel : Notify
{
    private CustomCommand selectedAlbum;
    private List<AlbumApi> albums;

    public CustomCommand SelectedAlbum
    {
        get => selectedAlbum;
        set
        {
            selectedAlbum = value;
            SignalChanged();
        }
    }

    public List<AlbumApi> Albums 
    {
        get => albums;
        set 
        {
            albums = value;
            SignalChanged("Albums");
        } 
    }

    public CustomCommand NewAlbum { get; set; }
    public UserApi ProfileUser { get; set; }
    public CustomCommand Edit { get; set; }
    public CustomCommand EditAlbum { get; set; }
    public CustomCommand DeleteAlbum { get; set; }
    public CustomCommand Refresh { get; set; }


    public ProfilePageViewModel()
    {
        Task.Run(GetUserId);
        Task.Run(GetAlbumsList);

        Refresh = new CustomCommand(() =>
        {
            Task.Run(GetUserId);
            Task.Run(GetAlbumsList);
        });


        Edit = new CustomCommand(() =>
        {
            EditUserWindow euw = new EditUserWindow();
            euw.ShowDialog();
            Thread.Sleep(1000);
            Task.Run(GetUserId);
            
        });

        NewAlbum = new CustomCommand(() =>
        {
            AddAlbumWindow albumWindow = new AddAlbumWindow();
            albumWindow.Show();
        });
    }


    public async Task GetUserId()
    {
        var t = SingInWindowViewModel.UsId;
        var result = await Api.GetAsync<UserApi>(t, "User");
        ProfileUser = result;
        SignalChanged("ProfileUser");
    }

    public async Task GetAlbumsList()
    {
        var result = await Api.GetListAsync<AlbumApi[]>("Album");
        Albums = new List<AlbumApi>(result);
        SignalChanged("Albums");
    }


    public void Load()
    {
        Task.Run(GetUserId);
        Task.Run(GetAlbumsList);
    }
}

Окна редактирования ViewModel

public class EditUserWindowViewModel : Notify
{
    private BitmapImage image;
    public BitmapImage Image 
    { 
        get => image;
        set 
        {
            image = value;
            SignalChanged("Image");
        } 
    }

    public UserApi EditUser { get; set; }
    public CustomCommand SelectImage { get; set; }
    public CustomCommand SaveUser { get; set; }

    public EditUserWindowViewModel()
    {
        Task.Run(GetUserId);

        SaveUser = new CustomCommand(() =>
        {
            Task.Run(EditUsers);
            foreach (Window window in Application.Current.Windows)
            {
                if (window.DataContext == this)
                {
                    
                    CloseWin(window);
                }
            }
            
        });

        string directory = Environment.CurrentDirectory;
        SelectImage = new CustomCommand(() =>
        {
            OpenFileDialog ofd = new OpenFileDialog();
            if (ofd.ShowDialog() == true)
            {
                try
                {
                    var info = new FileInfo(ofd.FileName);
                    Image = GetImageFromPath(ofd.FileName);
                    EditUser.Image = $"/Resource/{info.Name}";
                    var newPath = directory.Substring(0, directory.Length) + EditUser.Image;
                    if (!File.Exists(newPath))
                        File.Copy(ofd.FileName, newPath, true);
                }
                catch (Exception)
                {
                    MessageBox.Show("Code error: Image Error", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
                }
            }
        });
    }

    public void CloseWin(object obj)
    {
        Window win = obj as Window;
        win.Close();
    }

    private BitmapImage GetImageFromPath(string url)
    {
        BitmapImage img = new BitmapImage();
        img.BeginInit();
        img.CacheOption = BitmapCacheOption.OnLoad;
        img.UriSource = new Uri(url, UriKind.Absolute);
        img.EndInit();
        return img;
    }

    public async Task EditUsers()
    {
        await Api.PutAsync<UserApi>(EditUser, "User");
    }

    public async Task GetUserId()
    {
        var t = SingInWindowViewModel.UsId;
        var result = await Api.GetAsync<UserApi>(t, "User");
        EditUser = result;
        SignalChanged("EditUser");
    }

    
    
}

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

Какое дочернее окно должно обновлять что? Это профиль пользователя редактируется?

Andy 13.02.2023 10:14

Вы должны изменить Task.Delay(200).Wait(); ждать Task.Delay(200); Почти всегда плохая идея использовать .Wait

Andy 13.02.2023 10:18
Laravel с Turbo JS
Laravel с Turbo JS
Turbo - это библиотека JavaScript для упрощения создания быстрых и высокоинтерактивных веб-приложений. Она работает с помощью техники под названием...
Типы ввода HTML: Лучшие практики и советы
Типы ввода HTML: Лучшие практики и советы
HTML, или HyperText Markup Language , является стандартным языком разметки, используемым для создания веб-страниц. Типы ввода HTML - это различные...
Аутсорсинг разработки PHP для индивидуальных веб-решений
Аутсорсинг разработки PHP для индивидуальных веб-решений
Услуги PHP-разработки могут быть экономически эффективным решением для компаний, которые ищут высококачественные услуги веб-разработки по доступным...
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
Слишком много useState? Давайте useReducer!
Слишком много useState? Давайте useReducer!
Современный фронтенд похож на старую добрую веб-разработку, но с одной загвоздкой: страница в браузере так же сложна, как и бэкенд.
Узнайте, как использовать теги &lt;ul&gt; и &lt;li&gt; для создания неупорядоченных списков в HTML
Узнайте, как использовать теги <ul> и <li> для создания неупорядоченных списков в HTML
HTML предоставляет множество тегов для структурирования и организации содержимого веб-страницы. Одним из наиболее часто используемых тегов для...
0
2
55
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я предлагаю вам использовать событие на каждом объекте страницы.

Ниже приведен минимальный пример кода.

Родительское окно ViewModel

public class MasterWinViewModel : Notify
{
    private object _curentPage;

    public object CurentPage
    {
        get { return _curentPage; }
        set
        {
            _curentPage = value;
            SignalChanged("CurentPage");
        }
    }
    
    public CustomCommand Profile { get; set; }       

    public MasterWinViewModel()
    {        
        Profile = new CustomCommand(() =>
        {
            ProfilePageViewModel profilepagevm = new ProfilePageViewModel();

            ProfilePageViewModel.OnEventFire += (sender, data) => 
            {
                //sender = profilepage
                //data = data object from profilepage
                //Do something with sent data.              
            }               

            ProfilePage profilepage = new ProfilePage();

            // Set DataContext. Not sure because I don't know ProfilePage's exact implementation.
            profilepage.DataContext = profilepagevm;

            CurentPage = profilepage;

            SignalChanged("CurentPage");
        });
    }      
}

ПрофильПажевиевМодел

public class ProfilePageViewModel : Notify
{    
    public delegate void EventDelegate(object sender, object data);
    
    public event EventDelegate OnEventFire = null;
    
    public ProfilePageViewModel()
    {
        
    } 
    
    public void EventFireMethod(object data) 
    {
        //Fire Event
        OnEventFire?.Invoke(this, data);
    }   
}

После вызова EventFireMethod в классе ProfilePage будет вызван метод обратного вызова.

Таким образом, вы можете отправлять данные между родительским окном и дочерним объектом страницы.

Ошибка: Код серьезности Описание Состояние подавления строки файла проекта Ошибка CS1061 «ProfilePage» не содержит определения «OnEventFire», и не удалось найти доступный метод расширения «OnEventFire», который принимает тип «ProfilePage» в качестве первого аргумента (возможно, директива using или ссылка на сборку были опущены). SpotyClient C:\Users\pokim\source\repos\SpotifyServer\SpotyClient\ViewMo‌del\MasterWinViewMod‌​el.cs 89 Active

memes 13.02.2023 11:20

Может так ProfilePageViewModel profilepage = new ProfilePageViewModel();?

memes 13.02.2023 12:03

@memes Да, у меня нет реализации вашего класса ProfilePage, поэтому вместо этого я использовал класс ProfilePageViewModel. Если вам нужно отправить данные в классе ProfilePage, вы также можете создать в нем делегата и событие.

KimMeo 14.02.2023 01:05

Другие вопросы по теме