diff --git a/src/Ryujinx/UI/ViewModels/AboutWindowViewModel.cs b/src/Ryujinx/UI/ViewModels/AboutWindowViewModel.cs
index 6bc1e1f03..979ae8253 100644
--- a/src/Ryujinx/UI/ViewModels/AboutWindowViewModel.cs
+++ b/src/Ryujinx/UI/ViewModels/AboutWindowViewModel.cs
@@ -1,6 +1,7 @@
 using Avalonia.Media.Imaging;
 using Avalonia.Styling;
 using Avalonia.Threading;
+using CommunityToolkit.Mvvm.ComponentModel;
 using Ryujinx.Ava.Common;
 using Ryujinx.Ava.Common.Locale;
 using Ryujinx.Ava.Utilities.Configuration;
@@ -8,42 +9,11 @@ using System;
 
 namespace Ryujinx.Ava.UI.ViewModels
 {
-    public class AboutWindowViewModel : BaseModel, IDisposable
+    public partial class AboutWindowViewModel : BaseModel, IDisposable
     {
-        private Bitmap _githubLogo;
-        private Bitmap _discordLogo;
-
-        private string _version;
-
-        public Bitmap GithubLogo
-        {
-            get => _githubLogo;
-            set
-            {
-                _githubLogo = value;
-                OnPropertyChanged();
-            }
-        }
-
-        public Bitmap DiscordLogo
-        {
-            get => _discordLogo;
-            set
-            {
-                _discordLogo = value;
-                OnPropertyChanged();
-            }
-        }
-
-        public string Version
-        {
-            get => _version;
-            set
-            {
-                _version = value;
-                OnPropertyChanged();
-            }
-        }
+        [ObservableProperty] private Bitmap _githubLogo;
+        [ObservableProperty] private Bitmap _discordLogo;
+        [ObservableProperty] private string _version;
 
         public string Developers => "GreemDev";
 
diff --git a/src/Ryujinx/UI/ViewModels/DownloadableContentManagerViewModel.cs b/src/Ryujinx/UI/ViewModels/DownloadableContentManagerViewModel.cs
index acc26decb..658568909 100644
--- a/src/Ryujinx/UI/ViewModels/DownloadableContentManagerViewModel.cs
+++ b/src/Ryujinx/UI/ViewModels/DownloadableContentManagerViewModel.cs
@@ -2,6 +2,7 @@ using Avalonia.Collections;
 using Avalonia.Controls.ApplicationLifetimes;
 using Avalonia.Platform.Storage;
 using Avalonia.Threading;
+using CommunityToolkit.Mvvm.ComponentModel;
 using DynamicData;
 using FluentAvalonia.UI.Controls;
 using Ryujinx.Ava.Common.Locale;
@@ -17,13 +18,13 @@ using Application = Avalonia.Application;
 
 namespace Ryujinx.Ava.UI.ViewModels
 {
-    public class DownloadableContentManagerViewModel : BaseModel
+    public partial class DownloadableContentManagerViewModel : BaseModel
     {
         private readonly ApplicationLibrary _applicationLibrary;
         private AvaloniaList<DownloadableContentModel> _downloadableContents = new();
-        private AvaloniaList<DownloadableContentModel> _selectedDownloadableContents = new();
-        private AvaloniaList<DownloadableContentModel> _views = new();
-        private bool _showBundledContentNotice = false;
+        [ObservableProperty] private AvaloniaList<DownloadableContentModel> _selectedDownloadableContents = new();
+        [ObservableProperty] private AvaloniaList<DownloadableContentModel> _views = new();
+        [ObservableProperty] private bool _showBundledContentNotice = false;
 
         private string _search;
         private readonly ApplicationData _applicationData;
@@ -41,26 +42,6 @@ namespace Ryujinx.Ava.UI.ViewModels
             }
         }
 
-        public AvaloniaList<DownloadableContentModel> Views
-        {
-            get => _views;
-            set
-            {
-                _views = value;
-                OnPropertyChanged();
-            }
-        }
-
-        public AvaloniaList<DownloadableContentModel> SelectedDownloadableContents
-        {
-            get => _selectedDownloadableContents;
-            set
-            {
-                _selectedDownloadableContents = value;
-                OnPropertyChanged();
-            }
-        }
-
         public string Search
         {
             get => _search;
@@ -77,16 +58,6 @@ namespace Ryujinx.Ava.UI.ViewModels
             get => string.Format(LocaleManager.Instance[LocaleKeys.DlcWindowHeading], DownloadableContents.Count);
         }
 
-        public bool ShowBundledContentNotice
-        {
-            get => _showBundledContentNotice;
-            set
-            {
-                _showBundledContentNotice = value;
-                OnPropertyChanged();
-            }
-        }
-
         public DownloadableContentManagerViewModel(ApplicationLibrary applicationLibrary, ApplicationData applicationData)
         {
             _applicationLibrary = applicationLibrary;
diff --git a/src/Ryujinx/UI/ViewModels/ModManagerViewModel.cs b/src/Ryujinx/UI/ViewModels/ModManagerViewModel.cs
index 9c26376ce..ce40ce16c 100644
--- a/src/Ryujinx/UI/ViewModels/ModManagerViewModel.cs
+++ b/src/Ryujinx/UI/ViewModels/ModManagerViewModel.cs
@@ -1,8 +1,7 @@
-using Avalonia;
 using Avalonia.Collections;
-using Avalonia.Controls.ApplicationLifetimes;
 using Avalonia.Platform.Storage;
 using Avalonia.Threading;
+using CommunityToolkit.Mvvm.ComponentModel;
 using DynamicData;
 using Gommon;
 using Ryujinx.Ava.Common.Locale;
@@ -18,13 +17,13 @@ using System.Linq;
 
 namespace Ryujinx.Ava.UI.ViewModels
 {
-    public class ModManagerViewModel : BaseModel
+    public partial class ModManagerViewModel : BaseModel
     {
         private readonly string _modJsonPath;
 
         private AvaloniaList<ModModel> _mods = new();
-        private AvaloniaList<ModModel> _views = new();
-        private AvaloniaList<ModModel> _selectedMods = new();
+        [ObservableProperty] private AvaloniaList<ModModel> _views = new();
+        [ObservableProperty] private AvaloniaList<ModModel> _selectedMods = new();
 
         private string _search;
         private readonly ulong _applicationId;
@@ -44,26 +43,6 @@ namespace Ryujinx.Ava.UI.ViewModels
             }
         }
 
-        public AvaloniaList<ModModel> Views
-        {
-            get => _views;
-            set
-            {
-                _views = value;
-                OnPropertyChanged();
-            }
-        }
-
-        public AvaloniaList<ModModel> SelectedMods
-        {
-            get => _selectedMods;
-            set
-            {
-                _selectedMods = value;
-                OnPropertyChanged();
-            }
-        }
-
         public string Search
         {
             get => _search;
@@ -143,8 +122,10 @@ namespace Ryujinx.Ava.UI.ViewModels
                 .Filter(Filter)
                 .Bind(out var view).AsObservableList();
 
+#pragma warning disable MVVMTK0034 // Event to update is fired below
             _views.Clear();
             _views.AddRange(view);
+#pragma warning restore MVVMTK0034
 
             SelectedMods = new(Views.Where(x => x.Enabled));
 
diff --git a/src/Ryujinx/UI/ViewModels/SettingsHacksViewModel.cs b/src/Ryujinx/UI/ViewModels/SettingsHacksViewModel.cs
index 4cfbc8957..5096a716d 100644
--- a/src/Ryujinx/UI/ViewModels/SettingsHacksViewModel.cs
+++ b/src/Ryujinx/UI/ViewModels/SettingsHacksViewModel.cs
@@ -1,9 +1,10 @@
-using Gommon;
+using CommunityToolkit.Mvvm.ComponentModel;
+using Gommon;
 using Ryujinx.Ava.Utilities.Configuration;
 
 namespace Ryujinx.Ava.UI.ViewModels
 {
-    public class SettingsHacksViewModel : BaseModel
+    public partial class SettingsHacksViewModel : BaseModel
     {
         private readonly SettingsViewModel _baseViewModel;
 
@@ -14,31 +15,9 @@ namespace Ryujinx.Ava.UI.ViewModels
             _baseViewModel = settingsVm;
         }
 
-        private bool _xc2MenuSoftlockFix = ConfigurationState.Instance.Hacks.Xc2MenuSoftlockFix;
-        private bool _shaderTranslationThreadSleep = ConfigurationState.Instance.Hacks.EnableShaderTranslationDelay;
+        [ObservableProperty] private bool _xc2MenuSoftlockFix = ConfigurationState.Instance.Hacks.Xc2MenuSoftlockFix;
+        [ObservableProperty] private bool _shaderTranslationDelayEnabled = ConfigurationState.Instance.Hacks.EnableShaderTranslationDelay;
         private int _shaderTranslationSleepDelay = ConfigurationState.Instance.Hacks.ShaderTranslationDelay;
-        
-        public bool Xc2MenuSoftlockFixEnabled
-        {
-            get => _xc2MenuSoftlockFix;
-            set
-            {
-                _xc2MenuSoftlockFix = value;
-                
-                OnPropertyChanged();
-            }
-        }
-        
-        public bool ShaderTranslationDelayEnabled
-        {
-            get => _shaderTranslationThreadSleep;
-            set
-            {
-                _shaderTranslationThreadSleep = value;
-                
-                OnPropertyChanged();
-            }
-        }
 
         public string ShaderTranslationDelayValueText => $"{ShaderTranslationDelay}ms"; 
         
diff --git a/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs b/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs
index a5bdd2f88..39df76aa4 100644
--- a/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs
+++ b/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs
@@ -756,7 +756,7 @@ namespace Ryujinx.Ava.UI.ViewModels
             config.Multiplayer.LdnServer.Value = LdnServer;
             
             // Dirty Hacks
-            config.Hacks.Xc2MenuSoftlockFix.Value = DirtyHacks.Xc2MenuSoftlockFixEnabled;
+            config.Hacks.Xc2MenuSoftlockFix.Value = DirtyHacks.Xc2MenuSoftlockFix;
             config.Hacks.EnableShaderTranslationDelay.Value = DirtyHacks.ShaderTranslationDelayEnabled;
             config.Hacks.ShaderTranslationDelay.Value = DirtyHacks.ShaderTranslationDelay;
 
diff --git a/src/Ryujinx/UI/ViewModels/TitleUpdateViewModel.cs b/src/Ryujinx/UI/ViewModels/TitleUpdateViewModel.cs
index 0748efeb4..86d59d6b4 100644
--- a/src/Ryujinx/UI/ViewModels/TitleUpdateViewModel.cs
+++ b/src/Ryujinx/UI/ViewModels/TitleUpdateViewModel.cs
@@ -1,74 +1,32 @@
 using Avalonia.Collections;
-using Avalonia.Controls.ApplicationLifetimes;
 using Avalonia.Platform.Storage;
 using Avalonia.Threading;
+using CommunityToolkit.Mvvm.ComponentModel;
 using FluentAvalonia.UI.Controls;
 using Ryujinx.Ava.Common.Locale;
 using Ryujinx.Ava.Common.Models;
 using Ryujinx.Ava.UI.Helpers;
 using Ryujinx.Ava.Utilities.AppLibrary;
-using Ryujinx.HLE.FileSystem;
 using System.Collections.Generic;
 using System.IO;
 using System.Linq;
 using System.Threading.Tasks;
-using Application = Avalonia.Application;
 
 namespace Ryujinx.Ava.UI.ViewModels
 {
-    public record TitleUpdateViewNoUpdateSentinal();
+    public record TitleUpdateViewModelNoUpdate;
 
-    public class TitleUpdateViewModel : BaseModel
+    public partial class TitleUpdateViewModel : BaseModel
     {
         private ApplicationLibrary ApplicationLibrary { get; }
         private ApplicationData ApplicationData { get; }
 
-        private AvaloniaList<TitleUpdateModel> _titleUpdates = new();
-        private AvaloniaList<object> _views = new();
-        private object _selectedUpdate = new TitleUpdateViewNoUpdateSentinal();
-        private bool _showBundledContentNotice = false;
+        [ObservableProperty] private AvaloniaList<TitleUpdateModel> _titleUpdates = new();
+        [ObservableProperty] private AvaloniaList<object> _views = new();
+        [ObservableProperty] private object _selectedUpdate = new TitleUpdateViewModelNoUpdate();
+        [ObservableProperty] private bool _showBundledContentNotice;
 
-        public AvaloniaList<TitleUpdateModel> TitleUpdates
-        {
-            get => _titleUpdates;
-            set
-            {
-                _titleUpdates = value;
-                OnPropertyChanged();
-            }
-        }
-
-        public AvaloniaList<object> Views
-        {
-            get => _views;
-            set
-            {
-                _views = value;
-                OnPropertyChanged();
-            }
-        }
-
-        public object SelectedUpdate
-        {
-            get => _selectedUpdate;
-            set
-            {
-                _selectedUpdate = value;
-                OnPropertyChanged();
-            }
-        }
-
-        public bool ShowBundledContentNotice
-        {
-            get => _showBundledContentNotice;
-            set
-            {
-                _showBundledContentNotice = value;
-                OnPropertyChanged();
-            }
-        }
-
-        public IStorageProvider StorageProvider;
+        private readonly IStorageProvider _storageProvider;
 
         public TitleUpdateViewModel(ApplicationLibrary applicationLibrary, ApplicationData applicationData)
         {
@@ -76,7 +34,7 @@ namespace Ryujinx.Ava.UI.ViewModels
 
             ApplicationData = applicationData;
 
-            StorageProvider = RyujinxApp.MainWindow.StorageProvider;
+            _storageProvider = RyujinxApp.MainWindow.StorageProvider;
 
             LoadUpdates();
         }
@@ -87,7 +45,7 @@ namespace Ryujinx.Ava.UI.ViewModels
                 .Where(it => it.TitleUpdate.TitleIdBase == ApplicationData.IdBase);
 
             bool hasBundledContent = false;
-            SelectedUpdate = new TitleUpdateViewNoUpdateSentinal();
+            SelectedUpdate = new TitleUpdateViewModelNoUpdate();
             foreach ((TitleUpdateModel update, bool isSelected) in updates)
             {
                 TitleUpdates.Add(update);
@@ -113,12 +71,12 @@ namespace Ryujinx.Ava.UI.ViewModels
             var selected = SelectedUpdate;
 
             Views.Clear();
-            Views.Add(new TitleUpdateViewNoUpdateSentinal());
+            Views.Add(new TitleUpdateViewModelNoUpdate());
             Views.AddRange(sortedUpdates);
 
             SelectedUpdate = selected;
 
-            if (SelectedUpdate is TitleUpdateViewNoUpdateSentinal)
+            if (SelectedUpdate is TitleUpdateViewModelNoUpdate)
             {
                 SelectedUpdate = Views[0];
             }
@@ -176,7 +134,7 @@ namespace Ryujinx.Ava.UI.ViewModels
             }
             else if (update == SelectedUpdate as TitleUpdateModel)
             {
-                SelectedUpdate = new TitleUpdateViewNoUpdateSentinal();
+                SelectedUpdate = new TitleUpdateViewModelNoUpdate();
             }
 
             SortUpdates();
@@ -184,7 +142,7 @@ namespace Ryujinx.Ava.UI.ViewModels
 
         public async Task Add()
         {
-            var result = await StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions
+            var result = await _storageProvider.OpenFilePickerAsync(new FilePickerOpenOptions
             {
                 AllowMultiple = true,
                 FileTypeFilter = new List<FilePickerFileType>
diff --git a/src/Ryujinx/UI/ViewModels/UserFirmwareAvatarSelectorViewModel.cs b/src/Ryujinx/UI/ViewModels/UserFirmwareAvatarSelectorViewModel.cs
index b07bf78b9..29c81308b 100644
--- a/src/Ryujinx/UI/ViewModels/UserFirmwareAvatarSelectorViewModel.cs
+++ b/src/Ryujinx/UI/ViewModels/UserFirmwareAvatarSelectorViewModel.cs
@@ -1,4 +1,5 @@
 using Avalonia.Media;
+using CommunityToolkit.Mvvm.ComponentModel;
 using LibHac.Common;
 using LibHac.Fs;
 using LibHac.Fs.Fsa;
@@ -20,12 +21,12 @@ using Image = SkiaSharp.SKImage;
 
 namespace Ryujinx.Ava.UI.ViewModels
 {
-    internal class UserFirmwareAvatarSelectorViewModel : BaseModel
+    internal partial class UserFirmwareAvatarSelectorViewModel : BaseModel
     {
         private static readonly Dictionary<string, byte[]> _avatarStore = new();
 
-        private ObservableCollection<ProfileImageModel> _images;
-        private Color _backgroundColor = Colors.White;
+        [ObservableProperty] private ObservableCollection<ProfileImageModel> _images;
+        [ObservableProperty] private Color _backgroundColor = Colors.White;
 
         private int _selectedIndex;
 
@@ -34,27 +35,11 @@ namespace Ryujinx.Ava.UI.ViewModels
             _images = new ObservableCollection<ProfileImageModel>();
 
             LoadImagesFromStore();
-        }
-
-        public Color BackgroundColor
-        {
-            get => _backgroundColor;
-            set
+            PropertyChanged += (_, args) =>
             {
-                _backgroundColor = value;
-                OnPropertyChanged();
-                ChangeImageBackground();
-            }
-        }
-
-        public ObservableCollection<ProfileImageModel> Images
-        {
-            get => _images;
-            set
-            {
-                _images = value;
-                OnPropertyChanged();
-            }
+                if (args.PropertyName == nameof(BackgroundColor))
+                    ChangeImageBackground();
+            };
         }
 
         public int SelectedIndex
@@ -70,7 +55,7 @@ namespace Ryujinx.Ava.UI.ViewModels
                 }
                 else
                 {
-                    SelectedImage = _images[_selectedIndex].Data;
+                    SelectedImage = Images[_selectedIndex].Data;
                 }
 
                 OnPropertyChanged();
diff --git a/src/Ryujinx/UI/ViewModels/UserProfileImageSelectorViewModel.cs b/src/Ryujinx/UI/ViewModels/UserProfileImageSelectorViewModel.cs
index 8e7d41a55..36a9a62f9 100644
--- a/src/Ryujinx/UI/ViewModels/UserProfileImageSelectorViewModel.cs
+++ b/src/Ryujinx/UI/ViewModels/UserProfileImageSelectorViewModel.cs
@@ -1,18 +1,9 @@
+using CommunityToolkit.Mvvm.ComponentModel;
+
 namespace Ryujinx.Ava.UI.ViewModels
 {
-    internal class UserProfileImageSelectorViewModel : BaseModel
+    internal partial class UserProfileImageSelectorViewModel : BaseModel
     {
-        private bool _firmwareFound;
-
-        public bool FirmwareFound
-        {
-            get => _firmwareFound;
-
-            set
-            {
-                _firmwareFound = value;
-                OnPropertyChanged();
-            }
-        }
+        [ObservableProperty] private bool _firmwareFound;
     }
 }
diff --git a/src/Ryujinx/UI/ViewModels/UserSaveManagerViewModel.cs b/src/Ryujinx/UI/ViewModels/UserSaveManagerViewModel.cs
index 85adef005..187df0449 100644
--- a/src/Ryujinx/UI/ViewModels/UserSaveManagerViewModel.cs
+++ b/src/Ryujinx/UI/ViewModels/UserSaveManagerViewModel.cs
@@ -1,3 +1,4 @@
+using CommunityToolkit.Mvvm.ComponentModel;
 using DynamicData;
 using DynamicData.Binding;
 using Ryujinx.Ava.Common.Locale;
@@ -8,74 +9,31 @@ using System.Collections.ObjectModel;
 
 namespace Ryujinx.Ava.UI.ViewModels
 {
-    public class UserSaveManagerViewModel : BaseModel
+    public partial class UserSaveManagerViewModel : BaseModel
     {
-        private int _sortIndex;
-        private int _orderIndex;
-        private string _search;
-        private ObservableCollection<SaveModel> _saves = new();
-        private ObservableCollection<SaveModel> _views = new();
+        [ObservableProperty] private int _sortIndex;
+        [ObservableProperty] private int _orderIndex;
+        [ObservableProperty] private string _search;
+        [ObservableProperty] private ObservableCollection<SaveModel> _saves = new();
+        [ObservableProperty] private ObservableCollection<SaveModel> _views = new();
         private readonly AccountManager _accountManager;
 
         public string SaveManagerHeading => LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.SaveManagerHeading, _accountManager.LastOpenedUser.Name, _accountManager.LastOpenedUser.UserId);
 
-        public int SortIndex
-        {
-            get => _sortIndex;
-            set
-            {
-                _sortIndex = value;
-                OnPropertyChanged();
-                Sort();
-            }
-        }
-
-        public int OrderIndex
-        {
-            get => _orderIndex;
-            set
-            {
-                _orderIndex = value;
-                OnPropertyChanged();
-                Sort();
-            }
-        }
-
-        public string Search
-        {
-            get => _search;
-            set
-            {
-                _search = value;
-                OnPropertyChanged();
-                Sort();
-            }
-        }
-
-        public ObservableCollection<SaveModel> Saves
-        {
-            get => _saves;
-            set
-            {
-                _saves = value;
-                OnPropertyChanged();
-                Sort();
-            }
-        }
-
-        public ObservableCollection<SaveModel> Views
-        {
-            get => _views;
-            set
-            {
-                _views = value;
-                OnPropertyChanged();
-            }
-        }
-
         public UserSaveManagerViewModel(AccountManager accountManager)
         {
             _accountManager = accountManager;
+            PropertyChanged += (_, evt) =>
+            {
+                if (evt.PropertyName is
+                    nameof(SortIndex) or
+                    nameof(OrderIndex) or
+                    nameof(Search) or
+                    nameof(Saves))
+                {
+                    Sort();
+                }
+            };
         }
 
         public void Sort()
@@ -85,8 +43,10 @@ namespace Ryujinx.Ava.UI.ViewModels
                 .Sort(GetComparer())
                 .Bind(out var view).AsObservableList();
 
+#pragma warning disable MVVMTK0034
             _views.Clear();
             _views.AddRange(view);
+#pragma warning restore MVVMTK0034
             OnPropertyChanged(nameof(Views));
         }
 
@@ -94,7 +54,7 @@ namespace Ryujinx.Ava.UI.ViewModels
         {
             if (arg is SaveModel save)
             {
-                return string.IsNullOrWhiteSpace(_search) || save.Title.ToLower().Contains(_search.ToLower());
+                return string.IsNullOrWhiteSpace(Search) || save.Title.ToLower().Contains(Search.ToLower());
             }
 
             return false;
diff --git a/src/Ryujinx/UI/Views/Settings/SettingsHacksView.axaml b/src/Ryujinx/UI/Views/Settings/SettingsHacksView.axaml
index 2ef0cc74f..f1900a69a 100644
--- a/src/Ryujinx/UI/Views/Settings/SettingsHacksView.axaml
+++ b/src/Ryujinx/UI/Views/Settings/SettingsHacksView.axaml
@@ -37,7 +37,7 @@
                     ToolTip.Tip="{Binding DirtyHacks.Xc2MenuFixTooltip}">
                     <CheckBox
                         Margin="0"
-                        IsChecked="{Binding DirtyHacks.Xc2MenuSoftlockFixEnabled}"/>
+                        IsChecked="{Binding DirtyHacks.Xc2MenuSoftlockFix}"/>
                     <TextBlock
                         VerticalAlignment="Center"
                         Text="Xenoblade Chronicles 2 Menu Softlock Fix" />
diff --git a/src/Ryujinx/UI/Windows/TitleUpdateWindow.axaml b/src/Ryujinx/UI/Windows/TitleUpdateWindow.axaml
index 0ba9bc7d8..a8ec5d29a 100644
--- a/src/Ryujinx/UI/Windows/TitleUpdateWindow.axaml
+++ b/src/Ryujinx/UI/Windows/TitleUpdateWindow.axaml
@@ -95,7 +95,7 @@
                         </Panel>
                     </DataTemplate>
                     <DataTemplate
-                        DataType="viewModels:TitleUpdateViewNoUpdateSentinal">
+                        DataType="viewModels:TitleUpdateViewModelNoUpdate">
                         <Panel
                             Height="33"
                             Margin="10">