diff --git a/src/Markup/Avalonia.Markup/Avalonia.Markup.csproj b/src/Markup/Avalonia.Markup/Avalonia.Markup.csproj
index 89e2c096ee..7b9cd0212e 100644
--- a/src/Markup/Avalonia.Markup/Avalonia.Markup.csproj
+++ b/src/Markup/Avalonia.Markup/Avalonia.Markup.csproj
@@ -2,6 +2,8 @@
netstandard2.0
Avalonia
+ Enable
+ CS8600;CS8602;CS8603
diff --git a/src/Markup/Avalonia.Markup/Data/Binding.cs b/src/Markup/Avalonia.Markup/Data/Binding.cs
index bf43730481..50be598d7f 100644
--- a/src/Markup/Avalonia.Markup/Data/Binding.cs
+++ b/src/Markup/Avalonia.Markup/Data/Binding.cs
@@ -39,17 +39,17 @@ namespace Avalonia.Data
///
/// Gets or sets the name of the element to use as the binding source.
///
- public string ElementName { get; set; }
+ public string? ElementName { get; set; }
///
/// Gets or sets the relative source for the binding.
///
- public RelativeSource RelativeSource { get; set; }
+ public RelativeSource? RelativeSource { get; set; }
///
/// Gets or sets the source for the binding.
///
- public object Source { get; set; }
+ public object? Source { get; set; }
///
/// Gets or sets the binding path.
@@ -59,24 +59,36 @@ namespace Avalonia.Data
///
/// Gets or sets a function used to resolve types from names in the binding path.
///
- public Func TypeResolver { get; set; }
+ public Func? TypeResolver { get; set; }
- protected override ExpressionObserver CreateExpressionObserver(IAvaloniaObject target, AvaloniaProperty targetProperty, object anchor, bool enableDataValidation)
+ protected override ExpressionObserver CreateExpressionObserver(IAvaloniaObject target, AvaloniaProperty targetProperty, object? anchor, bool enableDataValidation)
{
- Contract.Requires(target != null);
- anchor = anchor ?? DefaultAnchor?.Target;
-
+ _ = target ?? throw new ArgumentNullException(nameof(target));
+
+ anchor ??= DefaultAnchor?.Target;
enableDataValidation = enableDataValidation && Priority == BindingPriority.LocalValue;
- INameScope nameScope = null;
+ INameScope? nameScope = null;
NameScope?.TryGetTarget(out nameScope);
var (node, mode) = ExpressionObserverBuilder.Parse(Path, enableDataValidation, TypeResolver, nameScope);
+ if (node is null)
+ {
+ throw new InvalidOperationException("Could not parse binding expression.");
+ }
+
+ IStyledElement GetSource()
+ {
+ return target as IStyledElement ??
+ anchor as IStyledElement ??
+ throw new ArgumentException("Could not find binding source: either target or anchor must be an IStyledElement.");
+ }
+
if (ElementName != null)
{
return CreateElementObserver(
- (target as IStyledElement) ?? (anchor as IStyledElement),
+ GetSource(),
ElementName,
node);
}
@@ -96,9 +108,7 @@ namespace Avalonia.Data
}
else
{
- return CreateSourceObserver(
- (target as IStyledElement) ?? (anchor as IStyledElement),
- node);
+ return CreateSourceObserver(GetSource(), node);
}
}
else if (RelativeSource.Mode == RelativeSourceMode.DataContext)
@@ -111,15 +121,11 @@ namespace Avalonia.Data
}
else if (RelativeSource.Mode == RelativeSourceMode.Self)
{
- return CreateSourceObserver(
- (target as IStyledElement) ?? (anchor as IStyledElement),
- node);
+ return CreateSourceObserver(GetSource(), node);
}
else if (RelativeSource.Mode == RelativeSourceMode.TemplatedParent)
{
- return CreateTemplatedParentObserver(
- (target as IStyledElement) ?? (anchor as IStyledElement),
- node);
+ return CreateTemplatedParentObserver(GetSource(), node);
}
else if (RelativeSource.Mode == RelativeSourceMode.FindAncestor)
{
@@ -128,10 +134,7 @@ namespace Avalonia.Data
throw new InvalidOperationException("AncestorType must be set for RelativeSourceMode.FindAncestor when searching the visual tree.");
}
- return CreateFindAncestorObserver(
- (target as IStyledElement) ?? (anchor as IStyledElement),
- RelativeSource,
- node);
+ return CreateFindAncestorObserver(GetSource(), RelativeSource, node);
}
else
{
diff --git a/src/Markup/Avalonia.Markup/Data/BindingBase.cs b/src/Markup/Avalonia.Markup/Data/BindingBase.cs
index 3dbc83a7df..c25ef49167 100644
--- a/src/Markup/Avalonia.Markup/Data/BindingBase.cs
+++ b/src/Markup/Avalonia.Markup/Data/BindingBase.cs
@@ -38,22 +38,22 @@ namespace Avalonia.Data
///
/// Gets or sets the to use.
///
- public IValueConverter Converter { get; set; }
+ public IValueConverter? Converter { get; set; }
///
/// Gets or sets a parameter to pass to .
///
- public object ConverterParameter { get; set; }
+ public object? ConverterParameter { get; set; }
///
/// Gets or sets the value to use when the binding is unable to produce a value.
///
- public object FallbackValue { get; set; }
+ public object? FallbackValue { get; set; }
///
/// Gets or sets the value to use when the binding result is null.
///
- public object TargetNullValue { get; set; }
+ public object? TargetNullValue { get; set; }
///
/// Gets or sets the binding mode.
@@ -68,26 +68,27 @@ namespace Avalonia.Data
///
/// Gets or sets the string format.
///
- public string StringFormat { get; set; }
+ public string? StringFormat { get; set; }
- public WeakReference DefaultAnchor { get; set; }
+ public WeakReference? DefaultAnchor { get; set; }
- public WeakReference NameScope { get; set; }
+ public WeakReference? NameScope { get; set; }
protected abstract ExpressionObserver CreateExpressionObserver(
IAvaloniaObject target,
AvaloniaProperty targetProperty,
- object anchor,
+ object? anchor,
bool enableDataValidation);
///
public InstancedBinding Initiate(
IAvaloniaObject target,
AvaloniaProperty targetProperty,
- object anchor = null,
+ object? anchor = null,
bool enableDataValidation = false)
{
- Contract.Requires(target != null);
+ _ = target ?? throw new ArgumentNullException(nameof(target));
+
anchor = anchor ?? DefaultAnchor?.Target;
enableDataValidation = enableDataValidation && Priority == BindingPriority.LocalValue;
@@ -133,18 +134,13 @@ namespace Avalonia.Data
IAvaloniaObject target,
ExpressionNode node,
bool targetIsDataContext,
- object anchor)
+ object? anchor)
{
- Contract.Requires(target != null);
+ _ = target ?? throw new ArgumentNullException(nameof(target));
if (!(target is IDataContextProvider))
{
- target = anchor as IDataContextProvider;
-
- if (target == null)
- {
- throw new InvalidOperationException("Cannot find a DataContext to bind to.");
- }
+ target = anchor as IDataContextProvider ?? throw new InvalidOperationException("Cannot find a DataContext to bind to.");
}
if (!targetIsDataContext)
@@ -171,10 +167,9 @@ namespace Avalonia.Data
string elementName,
ExpressionNode node)
{
- Contract.Requires(target != null);
+ _ = target ?? throw new ArgumentNullException(nameof(target));
- NameScope.TryGetTarget(out var scope);
- if (scope == null)
+ if (NameScope is null || !NameScope.TryGetTarget(out var scope) || scope is null)
throw new InvalidOperationException("Name scope is null or was already collected");
var result = new ExpressionObserver(
NameScopeLocator.Track(scope, elementName),
@@ -188,9 +183,9 @@ namespace Avalonia.Data
RelativeSource relativeSource,
ExpressionNode node)
{
- Contract.Requires(target != null);
+ _ = target ?? throw new ArgumentNullException(nameof(target));
- IObservable