diff --git a/CHANGELIST.md b/CHANGELIST.md
index 29fdf73d..4d91f82f 100644
--- a/CHANGELIST.md
+++ b/CHANGELIST.md
@@ -11,6 +11,7 @@
- Remove all but .NET 6 for AppVeyor packaging
- Place message boxes at center of main window (Deterous)
- Enable nullability in MPF
+- Enable nullability in MPF.UI.Core
### 2.7.0 (2023-10-11)
diff --git a/MPF.Core/Data/Options.cs b/MPF.Core/Data/Options.cs
index 8a283a25..91666c21 100644
--- a/MPF.Core/Data/Options.cs
+++ b/MPF.Core/Data/Options.cs
@@ -628,12 +628,16 @@ namespace MPF.Core.Data
/// Constructor taking an existing Options object
///
///
+#if NET48
public Options(Options source)
+#else
+ public Options(Options? source)
+#endif
{
#if NET48
- Settings = new Dictionary(source.Settings);
+ Settings = new Dictionary(source?.Settings ?? new Dictionary());
#else
- Settings = new Dictionary(source.Settings);
+ Settings = new Dictionary(source?.Settings ?? new Dictionary());
#endif
}
diff --git a/MPF.Core/UI/ViewModels/DiscInformationViewModel.cs b/MPF.Core/UI/ViewModels/DiscInformationViewModel.cs
index fdfafe8e..fe768be0 100644
--- a/MPF.Core/UI/ViewModels/DiscInformationViewModel.cs
+++ b/MPF.Core/UI/ViewModels/DiscInformationViewModel.cs
@@ -191,10 +191,14 @@ namespace MPF.Core.UI.ViewModels
///
/// Constructor
///
+#if NET48
public DiscInformationViewModel(Options options, SubmissionInfo submissionInfo)
+#else
+ public DiscInformationViewModel(Options options, SubmissionInfo? submissionInfo)
+#endif
{
Options = options;
- SubmissionInfo = submissionInfo.Clone() as SubmissionInfo ?? new SubmissionInfo();
+ SubmissionInfo = submissionInfo?.Clone() as SubmissionInfo ?? new SubmissionInfo();
}
#region Helpers
diff --git a/MPF.Core/UI/ViewModels/MainViewModel.cs b/MPF.Core/UI/ViewModels/MainViewModel.cs
index 33b09dd7..74cc3b90 100644
--- a/MPF.Core/UI/ViewModels/MainViewModel.cs
+++ b/MPF.Core/UI/ViewModels/MainViewModel.cs
@@ -981,7 +981,11 @@ namespace MPF.Core.UI.ViewModels
///
/// Indicates if the settings were saved or not
/// Options representing the new, saved values
+#if NET48
public void UpdateOptions(bool savedSettings, Data.Options newOptions)
+#else
+ public void UpdateOptions(bool savedSettings, Data.Options? newOptions)
+#endif
{
if (savedSettings)
{
@@ -990,7 +994,7 @@ namespace MPF.Core.UI.ViewModels
}
}
- #endregion
+#endregion
#region UI Functionality
diff --git a/MPF.UI.Core/ElementConverter.cs b/MPF.UI.Core/ElementConverter.cs
index 457922ba..600e42ef 100644
--- a/MPF.UI.Core/ElementConverter.cs
+++ b/MPF.UI.Core/ElementConverter.cs
@@ -30,7 +30,11 @@ namespace MPF.UI.Core
}
}
+#if NET48
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+#else
+ public object? ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+#endif
{
// If it's an IElement but ends up null
var element = value as IElement;
diff --git a/MPF.UI.Core/External/WPFCustomMessageBox/CustomMessageBox.cs b/MPF.UI.Core/External/WPFCustomMessageBox/CustomMessageBox.cs
index 089e7a6e..791d02a9 100644
--- a/MPF.UI.Core/External/WPFCustomMessageBox/CustomMessageBox.cs
+++ b/MPF.UI.Core/External/WPFCustomMessageBox/CustomMessageBox.cs
@@ -173,7 +173,11 @@ namespace WPFCustomMessageBox
///
/// If the message box closes automatically due to the being exceeded, this result is returned.
/// A System.Windows.MessageBoxResult value that specifies which message box button is clicked by the user.
+#if NET48
public static MessageBoxResult Show(Window owner, string messageBoxText, string caption, MessageBoxButton button, MessageBoxImage icon, int? timeout = null, MessageBoxResult timeoutResult = MessageBoxResult.None)
+#else
+ public static MessageBoxResult Show(Window owner, string? messageBoxText, string caption, MessageBoxButton button, MessageBoxImage icon, int? timeout = null, MessageBoxResult timeoutResult = MessageBoxResult.None)
+#endif
{
switch (button)
{
@@ -515,7 +519,11 @@ namespace WPFCustomMessageBox
/// The message box will close automatically after given milliseconds
/// If the message box closes automatically due to being exceeded, this result is returned.
/// A System.Windows.MessageBoxResult value that specifies which message box button is clicked by the user.
+#if NET48
private static MessageBoxResult ShowOKMessage(Window owner, string messageBoxText, string caption, string okButtonText, string cancelButtonText, MessageBoxImage? icon, int? timeout = null, MessageBoxResult timeoutResult = MessageBoxResult.None)
+#else
+ private static MessageBoxResult ShowOKMessage(Window? owner, string? messageBoxText, string caption, string? okButtonText, string? cancelButtonText, MessageBoxImage? icon, int? timeout = null, MessageBoxResult timeoutResult = MessageBoxResult.None)
+#endif
{
MessageBoxButton buttonLayout = string.IsNullOrEmpty(cancelButtonText) ? MessageBoxButton.OK : MessageBoxButton.OKCancel;
@@ -545,7 +553,11 @@ namespace WPFCustomMessageBox
/// The message box will close automatically after given milliseconds
/// If the message box closes automatically due to being exceeded, this result is returned.
/// A System.Windows.MessageBoxResult value that specifies which message box button is clicked by the user.
+#if NET48
private static MessageBoxResult ShowYesNoMessage(Window owner, string messageBoxText, string caption, string yesButtonText, string noButtonText, string cancelButtonText, MessageBoxImage? icon, int? timeout = null, MessageBoxResult timeoutResult = MessageBoxResult.None)
+#else
+ private static MessageBoxResult ShowYesNoMessage(Window? owner, string? messageBoxText, string caption, string? yesButtonText, string? noButtonText, string? cancelButtonText, MessageBoxImage? icon, int? timeout = null, MessageBoxResult timeoutResult = MessageBoxResult.None)
+#endif
{
MessageBoxButton buttonLayout = string.IsNullOrEmpty(cancelButtonText) ? MessageBoxButton.YesNo : MessageBoxButton.YesNoCancel;
diff --git a/MPF.UI.Core/External/WPFCustomMessageBox/CustomMessageBoxWindow.xaml.cs b/MPF.UI.Core/External/WPFCustomMessageBox/CustomMessageBoxWindow.xaml.cs
index 5630d47f..72952708 100644
--- a/MPF.UI.Core/External/WPFCustomMessageBox/CustomMessageBoxWindow.xaml.cs
+++ b/MPF.UI.Core/External/WPFCustomMessageBox/CustomMessageBoxWindow.xaml.cs
@@ -12,7 +12,11 @@ namespace WPFCustomMessageBox
{
private bool _removeTitleBarIcon = true;
+#if NET48
public string Caption
+#else
+ public string? Caption
+#endif
{
get
{
@@ -24,7 +28,11 @@ namespace WPFCustomMessageBox
}
}
+#if NET48
public string Message
+#else
+ public string? Message
+#endif
{
get
{
@@ -36,7 +44,11 @@ namespace WPFCustomMessageBox
}
}
+#if NET48
public string OkButtonText
+#else
+ public string? OkButtonText
+#endif
{
get
{
@@ -48,7 +60,11 @@ namespace WPFCustomMessageBox
}
}
+#if NET48
public string CancelButtonText
+#else
+ public string? CancelButtonText
+#endif
{
get
{
@@ -60,7 +76,11 @@ namespace WPFCustomMessageBox
}
}
+#if NET48
public string YesButtonText
+#else
+ public string? YesButtonText
+#endif
{
get
{
@@ -72,7 +92,11 @@ namespace WPFCustomMessageBox
}
}
+#if NET48
public string NoButtonText
+#else
+ public string? NoButtonText
+#endif
{
get
{
@@ -86,7 +110,11 @@ namespace WPFCustomMessageBox
public MessageBoxResult Result { get; set; }
+#if NET48
internal CustomMessageBoxWindow(Window owner, string message, string caption = null, MessageBoxButton? button = null, MessageBoxImage? image = null, bool removeTitleBarIcon = true)
+#else
+ internal CustomMessageBoxWindow(Window? owner, string? message, string? caption = null, MessageBoxButton? button = null, MessageBoxImage? image = null, bool removeTitleBarIcon = true)
+#endif
{
InitializeComponent();
diff --git a/MPF.UI.Core/External/WPFCustomMessageBox/Util.cs b/MPF.UI.Core/External/WPFCustomMessageBox/Util.cs
index 24d6de55..ea64f77c 100644
--- a/MPF.UI.Core/External/WPFCustomMessageBox/Util.cs
+++ b/MPF.UI.Core/External/WPFCustomMessageBox/Util.cs
@@ -60,7 +60,11 @@ namespace WPFCustomMessageBox
///
///
///
+#if NET48
internal static string TryAddKeyboardAccellerator(this string input)
+#else
+ internal static string? TryAddKeyboardAccellerator(this string? input)
+#endif
{
if (input == null)
return input;
diff --git a/MPF.UI.Core/MPF.UI.Core.csproj b/MPF.UI.Core/MPF.UI.Core.csproj
index 51c09f2b..4438f777 100644
--- a/MPF.UI.Core/MPF.UI.Core.csproj
+++ b/MPF.UI.Core/MPF.UI.Core.csproj
@@ -10,6 +10,10 @@
2.7.0
+
+ enable
+
+
diff --git a/MPF.UI.Core/Theme.cs b/MPF.UI.Core/Theme.cs
index 798da485..238c0dcc 100644
--- a/MPF.UI.Core/Theme.cs
+++ b/MPF.UI.Core/Theme.cs
@@ -6,39 +6,63 @@ namespace MPF.UI.Core
///
/// Represents all required mapping values for the UI
///
- public class Theme
+ public abstract class Theme
{
#region Application-Wide
///
/// SolidColorBrush used to paint the active window's border.
///
- public SolidColorBrush ActiveBorderBrush { get; set; }
+#if NET48
+ public SolidColorBrush ActiveBorderBrush { get; protected set; }
+#else
+ public SolidColorBrush? ActiveBorderBrush { get; protected set; }
+#endif
///
/// SolidColorBrush that paints the face of a three-dimensional display element.
///
- public SolidColorBrush ControlBrush { get; set; }
+#if NET48
+ public SolidColorBrush ControlBrush { get; protected set; }
+#else
+ public SolidColorBrush? ControlBrush { get; protected set; }
+#endif
///
/// SolidColorBrush that paints text in a three-dimensional display element.
///
- public SolidColorBrush ControlTextBrush { get; set; }
+#if NET48
+ public SolidColorBrush ControlTextBrush { get; protected set; }
+#else
+ public SolidColorBrush? ControlTextBrush { get; protected set; }
+#endif
///
/// SolidColorBrush that paints disabled text.
///
- public SolidColorBrush GrayTextBrush { get; set; }
+#if NET48
+ public SolidColorBrush GrayTextBrush { get; protected set; }
+#else
+ public SolidColorBrush? GrayTextBrush { get; protected set; }
+#endif
///
/// SolidColorBrush that paints the background of a window's client area.
///
- public SolidColorBrush WindowBrush { get; set; }
+#if NET48
+ public SolidColorBrush WindowBrush { get; protected set; }
+#else
+ public SolidColorBrush? WindowBrush { get; protected set; }
+#endif
///
/// SolidColorBrush that paints the text in the client area of a window.
///
- public SolidColorBrush WindowTextBrush { get; set; }
+#if NET48
+ public SolidColorBrush WindowTextBrush { get; protected set; }
+#else
+ public SolidColorBrush? WindowTextBrush { get; protected set; }
+#endif
#endregion
@@ -47,22 +71,38 @@ namespace MPF.UI.Core
///
/// Brush for the Button.Disabled.Background resource
///
- public Brush Button_Disabled_Background { get; set; }
+#if NET48
+ public Brush Button_Disabled_Background { get; protected set; }
+#else
+ public Brush? Button_Disabled_Background { get; protected set; }
+#endif
///
/// Brush for the Button.MouseOver.Background resource
///
- public Brush Button_MouseOver_Background { get; set; }
+#if NET48
+ public Brush Button_MouseOver_Background { get; protected set; }
+#else
+ public Brush? Button_MouseOver_Background { get; protected set; }
+#endif
///
/// Brush for the Button.Pressed.Background resource
///
- public Brush Button_Pressed_Background { get; set; }
+#if NET48
+ public Brush Button_Pressed_Background { get; protected set; }
+#else
+ public Brush? Button_Pressed_Background { get; protected set; }
+#endif
///
/// Brush for the Button.Static.Background resource
///
- public Brush Button_Static_Background { get; set; }
+#if NET48
+ public Brush Button_Static_Background { get; protected set; }
+#else
+ public Brush? Button_Static_Background { get; protected set; }
+#endif
#endregion
@@ -71,62 +111,110 @@ namespace MPF.UI.Core
///
/// Brush for the ComboBox.Disabled.Background resource
///
- public Brush ComboBox_Disabled_Background { get; set; }
+#if NET48
+ public Brush ComboBox_Disabled_Background { get; protected set; }
+#else
+ public Brush? ComboBox_Disabled_Background { get; protected set; }
+#endif
///
/// Brush for the ComboBox.Disabled.Editable.Background resource
///
- public Brush ComboBox_Disabled_Editable_Background { get; set; }
+#if NET48
+ public Brush ComboBox_Disabled_Editable_Background { get; protected set; }
+#else
+ public Brush? ComboBox_Disabled_Editable_Background { get; protected set; }
+#endif
///
/// Brush for the ComboBox.Disabled.Editable.Button.Background resource
///
- public Brush ComboBox_Disabled_Editable_Button_Background { get; set; }
+#if NET48
+ public Brush ComboBox_Disabled_Editable_Button_Background { get; protected set; }
+#else
+ public Brush? ComboBox_Disabled_Editable_Button_Background { get; protected set; }
+#endif
///
/// Brush for the ComboBox.MouseOver.Background resource
///
- public Brush ComboBox_MouseOver_Background { get; set; }
+#if NET48
+ public Brush ComboBox_MouseOver_Background { get; protected set; }
+#else
+ public Brush? ComboBox_MouseOver_Background { get; protected set; }
+#endif
///
/// Brush for the ComboBox.MouseOver.Editable.Background resource
///
- public Brush ComboBox_MouseOver_Editable_Background { get; set; }
+#if NET48
+ public Brush ComboBox_MouseOver_Editable_Background { get; protected set; }
+#else
+ public Brush? ComboBox_MouseOver_Editable_Background { get; protected set; }
+#endif
///
/// Brush for the ComboBox.MouseOver.Editable.Button.Background resource
///
- public Brush ComboBox_MouseOver_Editable_Button_Background { get; set; }
+#if NET48
+ public Brush ComboBox_MouseOver_Editable_Button_Background { get; protected set; }
+#else
+ public Brush? ComboBox_MouseOver_Editable_Button_Background { get; protected set; }
+#endif
///
/// Brush for the ComboBox.Pressed.Background resource
///
- public Brush ComboBox_Pressed_Background { get; set; }
+#if NET48
+ public Brush ComboBox_Pressed_Background { get; protected set; }
+#else
+ public Brush? ComboBox_Pressed_Background { get; protected set; }
+#endif
///
/// Brush for the ComboBox.Pressed.Editable.Background resource
///
- public Brush ComboBox_Pressed_Editable_Background { get; set; }
+#if NET48
+ public Brush ComboBox_Pressed_Editable_Background { get; protected set; }
+#else
+ public Brush? ComboBox_Pressed_Editable_Background { get; protected set; }
+#endif
///
/// Brush for the ComboBox.Pressed.Editable.Button.Background resource
///
- public Brush ComboBox_Pressed_Editable_Button_Background { get; set; }
+#if NET48
+ public Brush ComboBox_Pressed_Editable_Button_Background { get; protected set; }
+#else
+ public Brush? ComboBox_Pressed_Editable_Button_Background { get; protected set; }
+#endif
///
/// Brush for the ComboBox.Static.Background resource
///
- public Brush ComboBox_Static_Background { get; set; }
+#if NET48
+ public Brush ComboBox_Static_Background { get; protected set; }
+#else
+ public Brush? ComboBox_Static_Background { get; protected set; }
+#endif
///
/// Brush for the ComboBox.Static.Editable.Background resource
///
- public Brush ComboBox_Static_Editable_Background { get; set; }
+#if NET48
+ public Brush ComboBox_Static_Editable_Background { get; protected set; }
+#else
+ public Brush? ComboBox_Static_Editable_Background { get; protected set; }
+#endif
///
/// Brush for the ComboBox.Static.Editable.Button.Background resource
///
- public Brush ComboBox_Static_Editable_Button_Background { get; set; }
+#if NET48
+ public Brush ComboBox_Static_Editable_Button_Background { get; protected set; }
+#else
+ public Brush? ComboBox_Static_Editable_Button_Background { get; protected set; }
+#endif
#endregion
@@ -135,7 +223,11 @@ namespace MPF.UI.Core
///
/// Brush for the CustomMessageBox.Static.Background resource
///
- public Brush CustomMessageBox_Static_Background { get; set; }
+#if NET48
+ public Brush CustomMessageBox_Static_Background { get; protected set; }
+#else
+ public Brush? CustomMessageBox_Static_Background { get; protected set; }
+#endif
#endregion
@@ -144,12 +236,20 @@ namespace MPF.UI.Core
///
/// Brush for the MenuItem.SubMenu.Background resource
///
- public Brush MenuItem_SubMenu_Background { get; set; }
+#if NET48
+ public Brush MenuItem_SubMenu_Background { get; protected set; }
+#else
+ public Brush? MenuItem_SubMenu_Background { get; protected set; }
+#endif
///
/// Brush for the MenuItem.SubMenu.Border resource
///
- public Brush MenuItem_SubMenu_Border { get; set; }
+#if NET48
+ public Brush MenuItem_SubMenu_Border { get; protected set; }
+#else
+ public Brush? MenuItem_SubMenu_Border { get; protected set; }
+#endif
#endregion
@@ -158,7 +258,11 @@ namespace MPF.UI.Core
///
/// Brush for the ProgressBar.Background resource
///
- public Brush ProgressBar_Background { get; set; }
+#if NET48
+ public Brush ProgressBar_Background { get; protected set; }
+#else
+ public Brush? ProgressBar_Background { get; protected set; }
+#endif
#endregion
@@ -167,7 +271,11 @@ namespace MPF.UI.Core
///
/// Brush for the ScrollViewer.ScrollBar.Background resource
///
- public Brush ScrollViewer_ScrollBar_Background { get; set; }
+#if NET48
+ public Brush ScrollViewer_ScrollBar_Background { get; protected set; }
+#else
+ public Brush? ScrollViewer_ScrollBar_Background { get; protected set; }
+#endif
#endregion
@@ -176,17 +284,29 @@ namespace MPF.UI.Core
///
/// Brush for the TabItem.Selected.Background resource
///
- public Brush TabItem_Selected_Background { get; set; }
+#if NET48
+ public Brush TabItem_Selected_Background { get; protected set; }
+#else
+ public Brush? TabItem_Selected_Background { get; protected set; }
+#endif
///
/// Brush for the TabItem.Static.Background resource
///
- public Brush TabItem_Static_Background { get; set; }
+#if NET48
+ public Brush TabItem_Static_Background { get; protected set; }
+#else
+ public Brush? TabItem_Static_Background { get; protected set; }
+#endif
///
/// Brush for the TabItem.Static.Border resource
///
- public Brush TabItem_Static_Border { get; set; }
+#if NET48
+ public Brush TabItem_Static_Border { get; protected set; }
+#else
+ public Brush? TabItem_Static_Border { get; protected set; }
+#endif
#endregion
@@ -195,7 +315,11 @@ namespace MPF.UI.Core
///
/// Brush for the TextBox.Static.Background resource
///
- public Brush TextBox_Static_Background { get; set; }
+#if NET48
+ public Brush TextBox_Static_Background { get; protected set; }
+#else
+ public Brush? TextBox_Static_Background { get; protected set; }
+#endif
#endregion
diff --git a/MPF.UI.Core/UserControls/LogOutput.xaml.cs b/MPF.UI.Core/UserControls/LogOutput.xaml.cs
index 7ba86777..22ed8190 100644
--- a/MPF.UI.Core/UserControls/LogOutput.xaml.cs
+++ b/MPF.UI.Core/UserControls/LogOutput.xaml.cs
@@ -29,7 +29,11 @@ namespace MPF.UI.Core.UserControls
///
/// Cached value of the last line written
///
+#if NET48
private Run lastLine = null;
+#else
+ private Run? lastLine = null;
+#endif
public LogOutput()
{
@@ -164,6 +168,7 @@ namespace MPF.UI.Core.UserControls
{
Dispatcher.Invoke(() =>
{
+ if (lastLine == null) lastLine = new Run();
lastLine.Text = logLine.Text;
lastLine.Foreground = logLine.GetForegroundColor();
});
diff --git a/MPF.UI.Core/Windows/DiscInformationWindow.xaml.cs b/MPF.UI.Core/Windows/DiscInformationWindow.xaml.cs
index 2ad08719..64bfa0b1 100644
--- a/MPF.UI.Core/Windows/DiscInformationWindow.xaml.cs
+++ b/MPF.UI.Core/Windows/DiscInformationWindow.xaml.cs
@@ -15,12 +15,16 @@ namespace MPF.UI.Core.Windows
///
/// Read-only access to the current disc information view model
///
- public DiscInformationViewModel DiscInformationViewModel => DataContext as DiscInformationViewModel;
+ public DiscInformationViewModel DiscInformationViewModel => DataContext as DiscInformationViewModel ?? new DiscInformationViewModel(new Options(), new SubmissionInfo());
///
/// Constructor
///
+#if NET48
public DiscInformationWindow(Options options, SubmissionInfo submissionInfo)
+#else
+ public DiscInformationWindow(Options options, SubmissionInfo? submissionInfo)
+#endif
{
InitializeComponent();
DataContext = new DiscInformationViewModel(options, submissionInfo);
@@ -47,7 +51,11 @@ namespace MPF.UI.Core.Windows
///
/// Manipulate fields based on the current disc
///
+#if NET48
private void ManipulateFields(Options options, SubmissionInfo submissionInfo)
+#else
+ private void ManipulateFields(Options options, SubmissionInfo? submissionInfo)
+#endif
{
// Enable tabs in all fields, if required
if (options.EnableTabsInInputFields)
@@ -115,63 +123,71 @@ namespace MPF.UI.Core.Windows
///
/// TODO: Figure out how to bind the PartiallyMatchedIDs array to a text box
/// TODO: Convert visibility to a binding
+#if NET48
private void HideReadOnlyFields(SubmissionInfo submissionInfo)
+#else
+ private void HideReadOnlyFields(SubmissionInfo? submissionInfo)
+#endif
{
- if (submissionInfo?.FullyMatchedID == null)
+ // If there's no submission information
+ if (submissionInfo == null)
+ return;
+
+ if (submissionInfo.FullyMatchedID == null)
FullyMatchedID.Visibility = Visibility.Collapsed;
- if (submissionInfo?.PartiallyMatchedIDs == null)
+ if (submissionInfo.PartiallyMatchedIDs == null)
PartiallyMatchedIDs.Visibility = Visibility.Collapsed;
else
PartiallyMatchedIDs.Text = string.Join(", ", submissionInfo.PartiallyMatchedIDs);
- if (submissionInfo?.CopyProtection?.AntiModchip == null)
+ if (submissionInfo.CopyProtection?.AntiModchip == null)
AntiModchip.Visibility = Visibility.Collapsed;
- if (submissionInfo?.TracksAndWriteOffsets?.OtherWriteOffsets == null)
+ if (submissionInfo.TracksAndWriteOffsets?.OtherWriteOffsets == null)
DiscOffset.Visibility = Visibility.Collapsed;
- if (submissionInfo?.CommonDiscInfo?.CommentsSpecialFields.Keys.Contains(SiteCode.DMIHash) != true)
+ if (submissionInfo.CommonDiscInfo?.CommentsSpecialFields?.Keys?.Contains(SiteCode.DMIHash) != true)
DMIHash.Visibility = Visibility.Collapsed;
- if (submissionInfo?.EDC?.EDC == null)
+ if (submissionInfo.EDC?.EDC == null)
EDC.Visibility = Visibility.Collapsed;
- if (string.IsNullOrWhiteSpace(submissionInfo?.CommonDiscInfo?.ErrorsCount))
+ if (string.IsNullOrWhiteSpace(submissionInfo.CommonDiscInfo?.ErrorsCount))
ErrorsCount.Visibility = Visibility.Collapsed;
- if (string.IsNullOrWhiteSpace(submissionInfo?.CommonDiscInfo?.EXEDateBuildDate))
+ if (string.IsNullOrWhiteSpace(submissionInfo.CommonDiscInfo?.EXEDateBuildDate))
EXEDateBuildDate.Visibility = Visibility.Collapsed;
- if (submissionInfo?.CommonDiscInfo?.CommentsSpecialFields.Keys.Contains(SiteCode.Filename) != true)
+ if (submissionInfo.CommonDiscInfo?.CommentsSpecialFields?.Keys.Contains(SiteCode.Filename) != true)
Filename.Visibility = Visibility.Collapsed;
- if (string.IsNullOrWhiteSpace(submissionInfo?.Extras?.Header))
+ if (string.IsNullOrWhiteSpace(submissionInfo.Extras?.Header))
Header.Visibility = Visibility.Collapsed;
- if (submissionInfo?.CommonDiscInfo?.CommentsSpecialFields.Keys.Contains(SiteCode.InternalName) != true)
+ if (submissionInfo.CommonDiscInfo?.CommentsSpecialFields?.Keys.Contains(SiteCode.InternalName) != true)
InternalName.Visibility = Visibility.Collapsed;
- if (submissionInfo?.CommonDiscInfo?.CommentsSpecialFields.Keys.Contains(SiteCode.InternalSerialName) != true)
+ if (submissionInfo.CommonDiscInfo?.CommentsSpecialFields?.Keys.Contains(SiteCode.InternalSerialName) != true)
InternalSerialName.Visibility = Visibility.Collapsed;
- if (submissionInfo?.CommonDiscInfo?.CommentsSpecialFields.Keys.Contains(SiteCode.Multisession) != true)
+ if (submissionInfo.CommonDiscInfo?.CommentsSpecialFields?.Keys.Contains(SiteCode.Multisession) != true)
Multisession.Visibility = Visibility.Collapsed;
- if (submissionInfo?.CopyProtection?.LibCrypt == null)
+ if (submissionInfo.CopyProtection?.LibCrypt == null)
LibCrypt.Visibility = Visibility.Collapsed;
- if (string.IsNullOrWhiteSpace(submissionInfo?.CopyProtection?.LibCryptData))
+ if (string.IsNullOrWhiteSpace(submissionInfo.CopyProtection?.LibCryptData))
LibCryptData.Visibility = Visibility.Collapsed;
- if (submissionInfo?.CommonDiscInfo?.CommentsSpecialFields.Keys.Contains(SiteCode.PFIHash) != true)
+ if (submissionInfo.CommonDiscInfo?.CommentsSpecialFields?.Keys.Contains(SiteCode.PFIHash) != true)
PFIHash.Visibility = Visibility.Collapsed;
- if (string.IsNullOrWhiteSpace(submissionInfo?.Extras?.PIC))
+ if (string.IsNullOrWhiteSpace(submissionInfo.Extras?.PIC))
PIC.Visibility = Visibility.Collapsed;
- if (string.IsNullOrWhiteSpace(submissionInfo?.Extras?.PVD))
+ if (string.IsNullOrWhiteSpace(submissionInfo.Extras?.PVD))
PVD.Visibility = Visibility.Collapsed;
- if (submissionInfo?.CommonDiscInfo?.CommentsSpecialFields.Keys.Contains(SiteCode.RingNonZeroDataStart) != true)
+ if (submissionInfo.CommonDiscInfo?.CommentsSpecialFields?.Keys.Contains(SiteCode.RingNonZeroDataStart) != true)
RingNonZeroDataStart.Visibility = Visibility.Collapsed;
- if (string.IsNullOrWhiteSpace(submissionInfo?.CopyProtection?.SecuROMData))
+ if (string.IsNullOrWhiteSpace(submissionInfo.CopyProtection?.SecuROMData))
SecuROMData.Visibility = Visibility.Collapsed;
- if (submissionInfo?.CommonDiscInfo?.CommentsSpecialFields.Keys.Contains(SiteCode.SSHash) != true)
+ if (submissionInfo.CommonDiscInfo?.CommentsSpecialFields?.Keys.Contains(SiteCode.SSHash) != true)
SSHash.Visibility = Visibility.Collapsed;
- if (string.IsNullOrWhiteSpace(submissionInfo?.Extras?.SecuritySectorRanges))
+ if (string.IsNullOrWhiteSpace(submissionInfo.Extras?.SecuritySectorRanges))
SecuritySectorRanges.Visibility = Visibility.Collapsed;
- if (submissionInfo?.CommonDiscInfo?.CommentsSpecialFields.Keys.Contains(SiteCode.SSVersion) != true)
+ if (submissionInfo.CommonDiscInfo?.CommentsSpecialFields?.Keys.Contains(SiteCode.SSVersion) != true)
SSVersion.Visibility = Visibility.Collapsed;
- if (submissionInfo?.CommonDiscInfo?.CommentsSpecialFields.Keys.Contains(SiteCode.UniversalHash) != true)
+ if (submissionInfo.CommonDiscInfo?.CommentsSpecialFields?.Keys.Contains(SiteCode.UniversalHash) != true)
UniversalHash.Visibility = Visibility.Collapsed;
- if (submissionInfo?.CommonDiscInfo?.CommentsSpecialFields.Keys.Contains(SiteCode.VolumeLabel) != true)
+ if (submissionInfo.CommonDiscInfo?.CommentsSpecialFields?.Keys.Contains(SiteCode.VolumeLabel) != true)
VolumeLabel.Visibility = Visibility.Collapsed;
- if (submissionInfo?.CommonDiscInfo?.CommentsSpecialFields.Keys.Contains(SiteCode.XeMID) != true)
+ if (submissionInfo.CommonDiscInfo?.CommentsSpecialFields?.Keys.Contains(SiteCode.XeMID) != true)
XeMID.Visibility = Visibility.Collapsed;
- if (submissionInfo?.CommonDiscInfo?.CommentsSpecialFields.Keys.Contains(SiteCode.XMID) != true)
+ if (submissionInfo.CommonDiscInfo?.CommentsSpecialFields?.Keys.Contains(SiteCode.XMID) != true)
XMID.Visibility = Visibility.Collapsed;
}
@@ -179,7 +195,11 @@ namespace MPF.UI.Core.Windows
/// Update visible fields and sections based on the media type
///
/// TODO: See if these can be done by binding
+#if NET48
private void UpdateFromDiscType(SubmissionInfo submissionInfo)
+#else
+ private void UpdateFromDiscType(SubmissionInfo? submissionInfo)
+#endif
{
// Sony-printed discs have layers in the opposite order
var system = submissionInfo?.CommonDiscInfo?.System;
@@ -326,7 +346,11 @@ namespace MPF.UI.Core.Windows
/// Update visible fields and sections based on the system type
///
/// TODO: See if these can be done by binding
+#if NET48
private void UpdateFromSystemType(SubmissionInfo submissionInfo)
+#else
+ private void UpdateFromSystemType(SubmissionInfo? submissionInfo)
+#endif
{
var system = submissionInfo?.CommonDiscInfo?.System;
switch (system)
@@ -337,7 +361,7 @@ namespace MPF.UI.Core.Windows
}
}
- #endregion
+#endregion
#region Event Handlers
diff --git a/MPF.UI.Core/Windows/MainWindow.xaml.cs b/MPF.UI.Core/Windows/MainWindow.xaml.cs
index 9b6d7fa9..683b963a 100644
--- a/MPF.UI.Core/Windows/MainWindow.xaml.cs
+++ b/MPF.UI.Core/Windows/MainWindow.xaml.cs
@@ -15,7 +15,7 @@ namespace MPF.UI.Core.Windows
///
/// Read-only access to the current main view model
///
- public MainViewModel MainViewModel => DataContext as MainViewModel;
+ public MainViewModel MainViewModel => DataContext as MainViewModel ?? new MainViewModel();
///
/// Constructor
@@ -95,8 +95,10 @@ namespace MPF.UI.Core.Windows
{
// Get the current path, if possible
string currentPath = MainViewModel.OutputPath;
- if (string.IsNullOrWhiteSpace(currentPath))
+ if (string.IsNullOrWhiteSpace(currentPath) && !string.IsNullOrWhiteSpace(MainViewModel.Options.DefaultOutputPath))
currentPath = Path.Combine(MainViewModel.Options.DefaultOutputPath, "track.bin");
+ else if (string.IsNullOrWhiteSpace(currentPath))
+ currentPath = "track.bin";
if (string.IsNullOrWhiteSpace(currentPath))
currentPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "track.bin");
@@ -104,7 +106,7 @@ namespace MPF.UI.Core.Windows
currentPath = Path.GetFullPath(currentPath);
// Get the directory
- string directory = Path.GetDirectoryName(currentPath);
+ var directory = Path.GetDirectoryName(currentPath);
// Get the filename
string filename = Path.GetFileName(currentPath);
@@ -128,7 +130,7 @@ namespace MPF.UI.Core.Windows
/// True to show the box even if it's the same, false to only show if it's different
public void CheckForUpdates(bool showIfSame)
{
- (bool different, string message, string url) = MainViewModel.CheckForUpdates();
+ (bool different, string message, var url) = MainViewModel.CheckForUpdates();
// If we have a new version, put it in the clipboard
if (different)
@@ -204,7 +206,11 @@ namespace MPF.UI.Core.Windows
///
/// SubmissionInfo object to display and possibly change
/// Dialog open result
+#if NET48
public (bool?, SubmissionInfo) ShowDiscInformationWindow(SubmissionInfo submissionInfo)
+#else
+ public (bool?, SubmissionInfo?) ShowDiscInformationWindow(SubmissionInfo? submissionInfo)
+#endif
{
if (MainViewModel.Options.ShowDiscEjectReminder)
CustomMessageBox.Show(this, "It is now safe to eject the disc", "Eject", MessageBoxButton.OK, MessageBoxImage.Information);
@@ -221,9 +227,17 @@ namespace MPF.UI.Core.Windows
// Copy back the submission info changes, if necessary
if (result == true)
+#if NET48
submissionInfo = discInformationWindow.DiscInformationViewModel.SubmissionInfo.Clone() as SubmissionInfo;
+#else
+ submissionInfo = (discInformationWindow.DiscInformationViewModel.SubmissionInfo.Clone() as SubmissionInfo)!;
+#endif
+#if NET48
return (result, submissionInfo);
+#else
+ return (result, submissionInfo!);
+#endif
}
///
@@ -268,10 +282,14 @@ namespace MPF.UI.Core.Windows
///
/// Handler for OptionsWindow OnUpdated event
///
+#if NET48
public void OnOptionsUpdated(object sender, EventArgs e)
+#else
+ public void OnOptionsUpdated(object? sender, EventArgs e)
+#endif
{
bool savedSettings = (sender as OptionsWindow)?.OptionsViewModel?.SavedSettings ?? false;
- var options = (sender as OptionsWindow).OptionsViewModel.Options;
+ var options = (sender as OptionsWindow)?.OptionsViewModel?.Options;
MainViewModel.UpdateOptions(savedSettings, options);
}
@@ -319,11 +337,11 @@ namespace MPF.UI.Core.Windows
///
public async void CopyProtectScanButtonClick(object sender, RoutedEventArgs e)
{
- (string output, string error) = await MainViewModel.ScanAndShowProtection();
+ var (output, error) = await MainViewModel.ScanAndShowProtection();
if (!MainViewModel.LogPanelExpanded)
{
- if (string.IsNullOrEmpty(error))
+ if (!string.IsNullOrEmpty(output) && string.IsNullOrEmpty(error))
CustomMessageBox.Show(this, output, "Detected Protection(s)", MessageBoxButton.OK, MessageBoxImage.Information);
else
CustomMessageBox.Show(this, "An exception occurred, see the log for details", "Error!", MessageBoxButton.OK, MessageBoxImage.Error);
diff --git a/MPF.UI.Core/Windows/OptionsWindow.xaml.cs b/MPF.UI.Core/Windows/OptionsWindow.xaml.cs
index 036abc04..c2c50b65 100644
--- a/MPF.UI.Core/Windows/OptionsWindow.xaml.cs
+++ b/MPF.UI.Core/Windows/OptionsWindow.xaml.cs
@@ -17,7 +17,7 @@ namespace MPF.UI.Core.Windows
///
/// Read-only access to the current options view model
///
- public OptionsViewModel OptionsViewModel => DataContext as OptionsViewModel;
+ public OptionsViewModel OptionsViewModel => DataContext as OptionsViewModel ?? new OptionsViewModel(new Options());
///
/// Constructor
@@ -46,7 +46,11 @@ namespace MPF.UI.Core.Windows
///
/// Browse and set a path based on the invoking button
///
+#if NET48
private void BrowseForPath(Window parent, System.Windows.Controls.Button button)
+#else
+ private void BrowseForPath(Window parent, System.Windows.Controls.Button? button)
+#endif
{
// If the button is null, we can't do anything
if (button == null)
@@ -58,8 +62,8 @@ namespace MPF.UI.Core.Windows
// TODO: hack for now, then we'll see
bool shouldBrowseForPath = pathSettingName == "DefaultOutputPath";
- string currentPath = TextBoxForPathSetting(parent, pathSettingName)?.Text;
- string initialDirectory = AppDomain.CurrentDomain.BaseDirectory;
+ var currentPath = TextBoxForPathSetting(parent, pathSettingName)?.Text;
+ var initialDirectory = AppDomain.CurrentDomain.BaseDirectory;
if (!shouldBrowseForPath && !string.IsNullOrEmpty(currentPath))
initialDirectory = Path.GetDirectoryName(Path.GetFullPath(currentPath));
@@ -88,7 +92,9 @@ namespace MPF.UI.Core.Windows
if (exists)
{
OptionsViewModel.Options[pathSettingName] = path;
- TextBoxForPathSetting(parent, pathSettingName).Text = path;
+ var textBox = TextBoxForPathSetting(parent, pathSettingName);
+ if (textBox != null)
+ textBox.Text = path;
}
else
{
@@ -108,7 +114,11 @@ namespace MPF.UI.Core.Windows
///
/// Setting name to find
/// TextBox for that setting
+#if NET48
private System.Windows.Controls.TextBox TextBoxForPathSetting(Window parent, string name) =>
+#else
+ private System.Windows.Controls.TextBox? TextBoxForPathSetting(Window parent, string name) =>
+#endif
parent.FindName(name + "TextBox") as System.Windows.Controls.TextBox;
///
@@ -119,7 +129,11 @@ namespace MPF.UI.Core.Windows
///
/// Create an open file dialog box
///
+#if NET48
private static OpenFileDialog CreateOpenFileDialog(string initialDirectory)
+#else
+ private static OpenFileDialog CreateOpenFileDialog(string? initialDirectory)
+#endif
{
return new OpenFileDialog()
{
@@ -142,7 +156,7 @@ namespace MPF.UI.Core.Windows
#if NET48
(bool? success, string message) = OptionsViewModel.TestRedumpLogin(RedumpUsernameTextBox.Text, RedumpPasswordBox.Password);
#else
- (bool? success, string message) = await OptionsViewModel.TestRedumpLogin(RedumpUsernameTextBox.Text, RedumpPasswordBox.Password);
+ (bool? success, string? message) = await OptionsViewModel.TestRedumpLogin(RedumpUsernameTextBox.Text, RedumpPasswordBox.Password);
#endif
if (success == true)
diff --git a/MPF/MPF.csproj b/MPF/MPF.csproj
index 1b05f073..a6ddc624 100644
--- a/MPF/MPF.csproj
+++ b/MPF/MPF.csproj
@@ -15,9 +15,9 @@
MPF.Test
-
- enable
-
+
+ enable
+