Есть родительское окно, в нем объявлена страница, на странице есть кнопка (Редактировать). По нажатию на кнопку откроется окно, после его закрытия данные в родительском окне должны обновиться.
Родительское окно 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");
}
}
Я пытался обновить данные после закрытия дочернего окна, но это не решило проблему. Потому что дочернее окно не знает о родительском окне.
Вы должны изменить Task.Delay(200).Wait(); ждать Task.Delay(200); Почти всегда плохая идея использовать .Wait
Я предлагаю вам использовать событие на каждом объекте страницы.
Ниже приведен минимальный пример кода.
Родительское окно 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\ViewModel\MasterWinViewModel.cs 89 Active
Может так ProfilePageViewModel profilepage = new ProfilePageViewModel();?
@memes Да, у меня нет реализации вашего класса ProfilePage, поэтому вместо этого я использовал класс ProfilePageViewModel. Если вам нужно отправить данные в классе ProfilePage, вы также можете создать в нем делегата и событие.
Какое дочернее окно должно обновлять что? Это профиль пользователя редактируется?