Skip to content

Commit 18bdae8

Browse files
Enable nullable reference types (#2069)
<!--- Provide a general summary of your changes in the Title above --> ## Description <!--- Describe your changes in detail --> This PR will enable `Nullable` to help catch potential null reference issues at compile time, improve code clarity, and align the samples with modern .NET best practices. ## Motivation and Context <!--- Why is this change required? What problem does it solve? --> <!--- If it fixes an open issue, please link to the issue here. --> Closes #2066. ## How Has This Been Tested? <!--- Please describe in detail how you tested your changes. --> <!--- Include details of your testing environment, and the tests you ran to --> <!--- see how your change affects other areas of the code, etc. --> ## Screenshots (if appropriate): ## Types of changes <!--- What types of changes does your code introduce? Put an `x` in all the boxes that apply: --> - [x] Bug fix (non-breaking change which fixes an issue) - [ ] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to change) ## Issues not Directly Related to This PR I'll use this section to note any unrelated issues I encounter while working on this PR. - Scratch Pad page: Clicking the Load button throws an exception when no local settings are present. - AnimatedIcon page: Clicking the button in the first sample and then closing the app results in an exception. - PullToRefresh page: Performing a pull-to-refresh on the second sample, then navigating to another page, triggers an exception. - RichEditBox page: Menu_Opening method contains duplicate code. --------- Co-authored-by: Marcel W. <marcel.alex.wagner@outlook.com>
1 parent 3b6ff8f commit 18bdae8

File tree

116 files changed

+835
-569
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

116 files changed

+835
-569
lines changed

WinUIGallery/App.xaml.cs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -116,10 +116,11 @@ private async void EnsureWindow()
116116
var targetPageArguments = string.Empty;
117117

118118
AppActivationArguments eventArgs = AppInstance.GetCurrent().GetActivatedEventArgs();
119-
if (eventArgs != null && eventArgs.Kind == ExtendedActivationKind.Protocol && eventArgs.Data is ProtocolActivatedEventArgs)
119+
if (eventArgs != null &&
120+
eventArgs.Kind == ExtendedActivationKind.Protocol &&
121+
eventArgs.Data is ProtocolActivatedEventArgs protocolArgs)
120122
{
121-
var ProtocolArgs = eventArgs.Data as ProtocolActivatedEventArgs;
122-
string uri = ProtocolArgs.Uri.LocalPath.Replace("/", "");
123+
string uri = protocolArgs.Uri.LocalPath.Replace("/", "");
123124
targetPageArguments = uri;
124125

125126
if (uri == "AllControls")
@@ -162,15 +163,15 @@ private void HandleExceptions(object sender, Microsoft.UI.Xaml.UnhandledExceptio
162163
if (NativeMethods.IsAppPackaged)
163164
{
164165
e.Handled = true; //Don't crash the app.
165-
166+
166167
//Create the notification.
167168
var notification = new AppNotificationBuilder()
168169
.AddText("An exception was thrown.")
169170
.AddText($"Type: {e.Exception.GetType()}")
170171
.AddText($"Message: {e.Message}\r\n" +
171172
$"HResult: {e.Exception.HResult}")
172173
.BuildNotification();
173-
174+
174175
//Show the notification
175176
AppNotificationManager.Default.Show(notification);
176177
}

WinUIGallery/Controls/ControlExample.xaml.cs

Lines changed: 25 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,12 @@ namespace WinUIGallery.Controls;
1919
/// </summary>
2020
public sealed class ControlExampleSubstitution : DependencyObject
2121
{
22-
public event TypedEventHandler<ControlExampleSubstitution, object> ValueChanged;
22+
public event TypedEventHandler<ControlExampleSubstitution, object?>? ValueChanged;
2323

24-
public string Key { get; set; }
24+
public string Key { get; set; } = string.Empty;
2525

26-
private object _value = null;
27-
public object Value
26+
private object? _value = null;
27+
public object? Value
2828
{
2929
get { return _value; }
3030
set
@@ -52,20 +52,15 @@ public string ValueAsString()
5252
return string.Empty;
5353
}
5454

55-
object value = Value;
55+
object? value = Value;
5656

5757
// For solid color brushes, use the underlying color.
5858
if (value is SolidColorBrush)
5959
{
6060
value = ((SolidColorBrush)value).Color;
6161
}
6262

63-
if (value == null)
64-
{
65-
return string.Empty;
66-
}
67-
68-
return value.ToString();
63+
return value?.ToString() ?? string.Empty;
6964
}
7065
}
7166

@@ -193,15 +188,19 @@ private enum SyntaxHighlightLanguage { Xml, CSharp };
193188

194189
private void SelectorBarItem_Loaded(object sender, RoutedEventArgs e)
195190
{
196-
var item = sender as SelectorBarItem;
197-
if (item == null)
191+
if (sender is not SelectorBarItem item)
198192
return;
199193

200-
if (item.Tag.ToString().Equals("Xaml", StringComparison.OrdinalIgnoreCase))
194+
PrepareSelectorBarItem(item);
195+
}
196+
197+
private void PrepareSelectorBarItem(SelectorBarItem item)
198+
{
199+
if (item.Tag.ToString()?.Equals("Xaml", StringComparison.OrdinalIgnoreCase) is true)
201200
{
202201
item.Visibility = string.IsNullOrEmpty(Xaml) && string.IsNullOrEmpty(XamlSource) ? Visibility.Collapsed : Visibility.Visible;
203202
}
204-
else if (item.Tag.ToString().Equals("CSharp", StringComparison.OrdinalIgnoreCase))
203+
else if (item.Tag.ToString()?.Equals("CSharp", StringComparison.OrdinalIgnoreCase) is true)
205204
{
206205
item.Visibility = string.IsNullOrEmpty(CSharp) && string.IsNullOrEmpty(CSharpSource) ? Visibility.Collapsed : Visibility.Visible;
207206
}
@@ -217,19 +216,18 @@ private void SelectorBarItem_Loaded(object sender, RoutedEventArgs e)
217216

218217
private static void OnXamlChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
219218
{
220-
var ctrl = (ControlExample)d;
221-
if (ctrl != null)
222-
{
223-
ctrl.SelectorBarItem_Loaded(ctrl.SelectorBarXamlItem, null);
224-
}
219+
if (d is not ControlExample ctrl)
220+
return;
221+
222+
ctrl.PrepareSelectorBarItem(ctrl.SelectorBarXamlItem);
225223
}
224+
226225
private static void OnCSharpChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
227226
{
228-
var ctrl = (ControlExample)d;
229-
if (ctrl != null)
230-
{
231-
ctrl.SelectorBarItem_Loaded(ctrl.SelectorBarCSharpItem, null);
232-
}
227+
if (d is not ControlExample ctrl)
228+
return;
229+
230+
ctrl.PrepareSelectorBarItem(ctrl.SelectorBarCSharpItem);
233231
}
234232

235233
private void SelectorBarControl_SelectionChanged(SelectorBar sender, SelectorBarSelectionChangedEventArgs args)
@@ -242,12 +240,12 @@ private void HandlePresenterVisibility()
242240
var selectedItem = SelectorBarControl.SelectedItem;
243241
if (selectedItem != null)
244242
{
245-
if (selectedItem.Tag.ToString().Equals("Xaml", StringComparison.OrdinalIgnoreCase))
243+
if (selectedItem.Tag.ToString()?.Equals("Xaml", StringComparison.OrdinalIgnoreCase) is true)
246244
{
247245
XamlContentPresenter.Visibility = Visibility.Visible;
248246
CSharpContentPresenter.Visibility = Visibility.Collapsed;
249247
}
250-
else if (selectedItem.Tag.ToString().Equals("CSharp", StringComparison.OrdinalIgnoreCase))
248+
else if (selectedItem.Tag.ToString()?.Equals("CSharp", StringComparison.OrdinalIgnoreCase) is true)
251249
{
252250
CSharpContentPresenter.Visibility = Visibility.Visible;
253251
XamlContentPresenter.Visibility = Visibility.Collapsed;

WinUIGallery/Controls/InlineColorPicker.xaml.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ public SolidColorBrush ColorBrush
4040
public static readonly DependencyProperty ColorBrushProperty =
4141
DependencyProperty.Register("ColorBrush", typeof(SolidColorBrush), typeof(InlineColorPicker), new PropertyMetadata(new SolidColorBrush(Microsoft.UI.Colors.White)));
4242

43-
public event EventHandler<Color> ColorChanged;
43+
public event EventHandler<Color>? ColorChanged;
4444

4545
public InlineColorPicker()
4646
{

WinUIGallery/Controls/PageHeader.xaml.cs

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,17 @@ public Visibility ThemeButtonVisibility
2121
public static readonly DependencyProperty ThemeButtonVisibilityProperty =
2222
DependencyProperty.Register("ThemeButtonVisibility", typeof(Visibility), typeof(PageHeader), new PropertyMetadata(Visibility.Visible));
2323

24-
public string PageName { get; set; }
25-
public Action CopyLinkAction { get; set; }
26-
public Action ToggleThemeAction { get; set; }
24+
public string PageName { get; set; } = string.Empty;
25+
public Action? CopyLinkAction { get; set; }
26+
public Action? ToggleThemeAction { get; set; }
2727

28-
public ControlInfoDataItem Item
28+
public ControlInfoDataItem? Item
2929
{
3030
get { return _item; }
3131
set { _item = value; }
3232
}
3333

34-
private ControlInfoDataItem _item;
34+
private ControlInfoDataItem? _item;
3535

3636
public PageHeader()
3737
{
@@ -86,6 +86,11 @@ private void OnCopyDontShowAgainButtonClick(TeachingTip sender, object args)
8686

8787
private void OnCopyLink()
8888
{
89+
if (this.Item is null)
90+
{
91+
return;
92+
}
93+
8994
ProtocolActivationClipboardHelper.Copy(this.Item);
9095
}
9196
public async void OnFeedBackButtonClick(object sender, RoutedEventArgs e)
@@ -107,12 +112,12 @@ private void UserControl_Loaded(object sender, RoutedEventArgs e)
107112

108113
private string GetFavoriteGlyph(bool? isFavorite)
109114
{
110-
return (bool)isFavorite ? "\uE735" : "\uE734";
115+
return isFavorite is true ? "\uE735" : "\uE734";
111116
}
112117

113118
private string GetFavoriteToolTip(bool? isFavorite)
114119
{
115-
return (bool)isFavorite ? "Remove from favorites" : "Add to favorites";
120+
return isFavorite is true ? "Remove from favorites" : "Add to favorites";
116121
}
117122

118123
private void FavoriteButton_Click(object sender, RoutedEventArgs e)

WinUIGallery/Controls/SampleCodePresenter.xaml.cs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ public IList<ControlExampleSubstitution> Substitutions
6060

6161
private string actualCode = "";
6262
private static Regex SubstitutionPattern = new Regex(@"\$\(([^\)]+)\)");
63-
private RichTextBlock sampleCodeRTB;
63+
private RichTextBlock? sampleCodeRTB;
6464

6565
public SampleCodePresenter()
6666
{
@@ -126,7 +126,7 @@ private void SampleCodePresenter_ActualThemeChanged(FrameworkElement sender, obj
126126
GenerateSyntaxHighlightedContent();
127127
}
128128

129-
private void OnValueChanged(ControlExampleSubstitution sender, object e)
129+
private void OnValueChanged(ControlExampleSubstitution sender, object? _)
130130
{
131131
GenerateSyntaxHighlightedContent();
132132
}
@@ -166,8 +166,7 @@ private async void FormatAndRenderSampleFromFile(string sourceRelativePath, Cont
166166
{
167167
if (sourceRelativePath != null && sourceRelativePath.EndsWith("txt"))
168168
{
169-
string sampleString = null;
170-
StorageFile file = null;
169+
StorageFile? file = null;
171170
if (!NativeMethods.IsAppPackaged)
172171
{
173172
var relativePath = GetDerivedSourceUnpackaged(sourceRelativePath);
@@ -182,7 +181,7 @@ private async void FormatAndRenderSampleFromFile(string sourceRelativePath, Cont
182181
file = await StorageFile.GetFileFromApplicationUriAsync(derivedSource);
183182
}
184183

185-
sampleString = await FileIO.ReadTextAsync(file);
184+
string sampleString = await FileIO.ReadTextAsync(file);
186185

187186
FormatAndRenderSampleFromString(sampleString, presenter, highlightLanguage);
188187
}
@@ -319,7 +318,7 @@ private void CopyCodeButton_Click(object sender, RoutedEventArgs e)
319318

320319
private void CodeScrollViewer_Loaded(object sender, RoutedEventArgs e)
321320
{
322-
ScrollBar horizontalScrollBar = FindHorizontalScrollBar(CodeScrollViewer);
321+
ScrollBar? horizontalScrollBar = FindHorizontalScrollBar(CodeScrollViewer);
323322
if (horizontalScrollBar != null)
324323
{
325324
// Create a timer and store it in the ScrollBar's Tag property.
@@ -361,7 +360,7 @@ private void HorizontalScrollBar_Scroll(object sender, ScrollEventArgs e)
361360
}
362361
}
363362

364-
private ScrollBar FindHorizontalScrollBar(DependencyObject element)
363+
private ScrollBar? FindHorizontalScrollBar(DependencyObject element)
365364
{
366365
if (element is ScrollBar sb && sb.Orientation == Orientation.Horizontal)
367366
{

WinUIGallery/Converters/MenuItemTemplateSelector.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,14 @@ namespace WinUIGallery.Converters;
1212
[ContentProperty(Name = "ItemTemplate")]
1313
partial class MenuItemTemplateSelector : DataTemplateSelector
1414
{
15-
public DataTemplate ItemTemplate { get; set; }
15+
public DataTemplate? ItemTemplate { get; set; }
1616

17-
protected override DataTemplate SelectTemplateCore(object item)
17+
protected override DataTemplate? SelectTemplateCore(object item)
1818
{
1919
return item is Separator ? SeparatorTemplate : item is Header ? HeaderTemplate : ItemTemplate;
2020
}
2121

22-
protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
22+
protected override DataTemplate? SelectTemplateCore(object item, DependencyObject container)
2323
{
2424
return item is Separator ? SeparatorTemplate : item is Header ? HeaderTemplate : ItemTemplate;
2525
}

WinUIGallery/Helpers/ControlInfoDataSource.cs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ public async Task<IEnumerable<ControlInfoDataGroup>> GetGroupsAsync()
5454
return _instance.Groups;
5555
}
5656

57-
public static async Task<ControlInfoDataGroup> GetGroupAsync(string uniqueId)
57+
public static async Task<ControlInfoDataGroup?> GetGroupAsync(string uniqueId)
5858
{
5959
await _instance.GetControlInfoDataAsync();
6060
// Simple linear search is acceptable for small data sets
@@ -63,7 +63,7 @@ public static async Task<ControlInfoDataGroup> GetGroupAsync(string uniqueId)
6363
return null;
6464
}
6565

66-
public static async Task<ControlInfoDataItem> GetItemAsync(string uniqueId)
66+
public static async Task<ControlInfoDataItem?> GetItemAsync(string uniqueId)
6767
{
6868
await _instance.GetControlInfoDataAsync();
6969
// Simple linear search is acceptable for small data sets
@@ -72,7 +72,7 @@ public static async Task<ControlInfoDataItem> GetItemAsync(string uniqueId)
7272
return null;
7373
}
7474

75-
public static async Task<ControlInfoDataGroup> GetGroupFromItemAsync(string uniqueId)
75+
public static async Task<ControlInfoDataGroup?> GetGroupFromItemAsync(string uniqueId)
7676
{
7777
await _instance.GetControlInfoDataAsync();
7878
var matches = _instance.Groups.Where((group) => group.Items.FirstOrDefault(item => item.UniqueId.Equals(uniqueId)) != null);
@@ -93,27 +93,30 @@ private async Task GetControlInfoDataAsync()
9393
var jsonText = await FileLoader.LoadText("Samples/Data/ControlInfoData.json");
9494
var controlInfoDataGroup = JsonSerializer.Deserialize(jsonText, typeof(Root), RootContext.Default) as Root;
9595

96+
if (controlInfoDataGroup is null)
97+
{
98+
return;
99+
}
100+
96101
lock (_lock)
97102
{
98103
string pageRoot = "WinUIGallery.ControlPages.";
99104

100105
controlInfoDataGroup.Groups.SelectMany(g => g.Items).ToList().ForEach(item =>
101106
{
102-
#nullable enable
103-
string? badgeString = item switch
107+
string badgeString = item switch
104108
{
105109
{ IsNew: true } => "New",
106110
{ IsUpdated: true } => "Updated",
107111
{ IsPreview: true } => "Preview",
108-
_ => null
112+
_ => string.Empty,
109113
};
110114
string pageString = $"{pageRoot}{item.UniqueId}Page";
111115
Type? pageType = Type.GetType(pageString);
112116

113117
item.BadgeString = badgeString;
114118
item.IncludedInBuild = pageType is not null;
115119
item.ImagePath ??= "ms-appx:///Assets/ControlImages/Placeholder.png";
116-
#nullable disable
117120
});
118121

119122
foreach (var group in controlInfoDataGroup.Groups)

WinUIGallery/Helpers/FileLoader.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ internal partial class FileLoader
1414
{
1515
public static async Task<string> LoadText(string relativeFilePath)
1616
{
17-
StorageFile file = null;
17+
StorageFile? file = null;
1818
if (!NativeMethods.IsAppPackaged)
1919
{
2020
var sourcePath = Path.GetFullPath(Path.Combine(AppContext.BaseDirectory, relativeFilePath));

WinUIGallery/Helpers/IconsDataSource.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,12 @@ public async Task<List<IconData>> LoadIcons()
3131
var jsonText = await FileLoader.LoadText("Samples/Data/IconsData.json");
3232
lock (_lock)
3333
{
34-
if (icons.Count == 0)
34+
if (icons.Count == 0 &&
35+
JsonSerializer.Deserialize(jsonText, typeof(List<IconData>), IconDataListContext.Default) is List<IconData> loadedIcons)
3536
{
36-
icons = JsonSerializer.Deserialize(jsonText, typeof(List<IconData>), IconDataListContext.Default) as List<IconData>;
37+
icons = loadedIcons;
3738
}
39+
3840
return icons;
3941
}
4042
}

0 commit comments

Comments
 (0)