我目前正在尝试下载一个文件并在我的应用程序中的 ListView 中显示该文件。我对此有一个问题。 ObservableCollection 确实发生了变化,并且值也不同了。然而,ListView 不知道它发生了变化,并且从不更新 UI 以显示更改。
到目前为止我已经尝试过但不起作用:
代码:
public class SoundBoardItem : INotifyPropertyChanged
{
public string SoundName { get; set; }
public string SoundLocation { get; set; }
public string SoundLocationIcon { get; set; }
public string SoundIconColor { get; set; }
public string SoundIconVisible { get; set; }
public string SoundIconTooltip { get; set; }
public string SoundKeybindForecolor { get; set; }
public string SoundKeybind { get; set; }
public bool ProgressRingEnabled { get; set; }
public bool ProgressRingIntermediate { get; set; }
public int ProgressRingProgress { get; set; }
public bool BtnEnabled { get; set; }
public SoundBoardItem(string soundName, string soundLocation, string soundLocationIcon, bool soundIconVisible, string soundIconTooltip, string soundKeybind, bool progressRingEnabled, bool btnEnabled, bool progressRingIntermediate = true, int progressRingProgress = 100, string soundIconColor = null, string soundKeybindForecolor = null)
{
SoundName = soundName;
SoundLocation = soundLocation;
SoundLocationIcon = soundLocationIcon;
SoundIconColor = soundIconColor;
SoundIconTooltip = soundIconTooltip;
SoundKeybindForecolor = soundKeybindForecolor;
SoundKeybind = soundKeybind;
ProgressRingEnabled = progressRingEnabled;
ProgressRingIntermediate = progressRingIntermediate;
ProgressRingProgress = progressRingProgress;
BtnEnabled = btnEnabled;
if (soundIconVisible == true) { SoundIconVisible = "Visible"; } else { SoundIconVisible = "Collapsed"; } // ease of use
}
public event PropertyChangedEventHandler PropertyChanged; // Also tried to use this in the ViewModel, but it didn't work either.
public void OnPropertyChanged(string message)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(message));
}
}
}
public class SoundBoardItemViewmodel
{
public ObservableCollection<SoundBoardItem> SoundBoardItems = new();
}
(内页)
private async void DownloadSoundFile(object sender, RoutedEventArgs e, string Name, string Url)
{
if (soundBoardItemViewmodel.SoundBoardItems.Any(x => x.SoundLocation == Url || x.SoundLocation == "Downloading... (" + Url + ")")) return;
YoutubeClient youtube = new();
StreamManifest streamManifest;
IStreamInfo streamInfo;
Stream audioOnlyStreamInfo;
string CurrentName;
var FilePath = AppDomain.CurrentDomain.BaseDirectory + "DownloadedSounds\\";
if (!Directory.Exists(FilePath))
Directory.CreateDirectory(FilePath);
// print file path to debug output
System.Diagnostics.Debug.WriteLine(FilePath);
try
{
streamManifest = await youtube.Videos.Streams.GetManifestAsync(Url);
streamInfo = streamManifest.GetAudioOnlyStreams().GetWithHighestBitrate();
audioOnlyStreamInfo = await youtube.Videos.Streams.GetAsync(streamInfo);
if (Name != "")
CurrentName = Name;
else
CurrentName = (await youtube.Videos.GetAsync(Url)).Title;
SoundBoardItem soundboardItem = new(CurrentName, "Downloading... (" + Url + ")", DownloadedFileIcon, false, "Downloaded File", "None", true, false, false, 0);
soundBoardItemViewmodel.SoundBoardItems.Add(soundboardItem);
var ProgressHandler = new Progress<double>(p =>
{
soundboardItem.ProgressRingProgress = Convert.ToInt32(p * 100); // same here; Changes do not show up in UI.
System.Diagnostics.Debug.WriteLine("Progress: " + Convert.ToInt32(p * 100) + "%");
});
await youtube.Videos.Streams.DownloadAsync(streamInfo, FilePath + $"video_DEBUG.{streamInfo.Container}", ProgressHandler);
soundboardItem.ProgressRingIntermediate = true;
soundboardItem.ProgressRingEnabled = false;
soundboardItem.BtnEnabled = true;
soundboardItem.SoundIconVisible = "Visible";
soundboardItem.SoundLocation = Url; // Values get changed but the changes do not appear.
}
catch (Exception ex)
{
await ShellPage.g_AppMessageBox.ShowMessagebox("Download Error", "An error has occured while downloading the youtube video: " + Url + "\n\nPlease make sure that the URL is correct and links to a valid youtube video.\nPlease note that age restricted videos are not supported.\n\nException: " + ex.Message, "", "", "Okay", ContentDialogButton.Close);
return;
}
}
这展示了如何使用
INotifyPropertyChanged
。
但我建议您使用 CommunityToolkit.Mvvm NuGet 包。它带来了源生成器,可以为您创建
INotifyPropertyChanged
相关的样板代码。你的代码应该是这样的:
// The class needs to be `partial`.
public partial SoundBoardItem : ObservableProperty
{
// The source generators will create a "SoundName" property
// implemented with INotifyPropertyChanged for you.
[ObservableProperty]
private string _soundName;
[ObservableProperty]
private string _soundLocation;
// The rest of your code here...
}