diff --git a/samples/XamlTestApplication/XamlTestApplication.csproj b/samples/XamlTestApplication/XamlTestApplication.csproj
index 42aaf4be21..14ab4adb26 100644
--- a/samples/XamlTestApplication/XamlTestApplication.csproj
+++ b/samples/XamlTestApplication/XamlTestApplication.csproj
@@ -84,6 +84,10 @@
+
+ {6417e941-21bc-467b-a771-0de389353ce6}
+ Perspex.Markup
+
{D211E587-D8BC-45B9-95A4-F297C8FA5200}
Perspex.Animation
diff --git a/samples/XamlTestApplicationPcl/StringNullOrEmpty.cs b/samples/XamlTestApplicationPcl/StringNullOrEmpty.cs
deleted file mode 100644
index c99dde4732..0000000000
--- a/samples/XamlTestApplicationPcl/StringNullOrEmpty.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright (c) The Perspex Project. All rights reserved.
-// Licensed under the MIT license. See licence.md file in the project root for full license information.
-
-using System;
-using System.Globalization;
-using Perspex;
-using Perspex.Markup;
-
-namespace XamlTestApplication
-{
- public class StringNullOrEmpty : IValueConverter
- {
- public static readonly StringNullOrEmpty Instance = new StringNullOrEmpty();
-
- public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
- {
- if (value == null)
- {
- return true;
- }
- else
- {
- var s = value as string;
- return s != null ? string.IsNullOrEmpty(s) : PerspexProperty.UnsetValue;
- }
- }
-
- public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
- {
- throw new NotImplementedException();
- }
- }
-}
diff --git a/samples/XamlTestApplicationPcl/TextBox.paml b/samples/XamlTestApplicationPcl/TextBox.paml
index 322f90499c..9d802d7d86 100644
--- a/samples/XamlTestApplicationPcl/TextBox.paml
+++ b/samples/XamlTestApplicationPcl/TextBox.paml
@@ -27,7 +27,7 @@
+ IsVisible="{TemplateBinding Path=Text, Converter={Static StringConverters.NullOrEmpty}}"/>
-
diff --git a/src/Markup/Perspex.Markup.Xaml/Context/PerspexWiringContext.cs b/src/Markup/Perspex.Markup.Xaml/Context/PerspexWiringContext.cs
index 29788cffab..2759d63167 100644
--- a/src/Markup/Perspex.Markup.Xaml/Context/PerspexWiringContext.cs
+++ b/src/Markup/Perspex.Markup.Xaml/Context/PerspexWiringContext.cs
@@ -61,8 +61,9 @@ namespace Perspex.Markup.Xaml.Context
var forcedAssemblies = new[]
{
- typeof (Control),
- typeof(Style)
+ typeof(Control),
+ typeof(Style),
+ typeof(IValueConverter),
}.Select(t => t.GetTypeInfo().Assembly);
foreach (var nsa in
diff --git a/src/Markup/Perspex.Markup/FuncValueConverter.cs b/src/Markup/Perspex.Markup/FuncValueConverter.cs
new file mode 100644
index 0000000000..6b64b48821
--- /dev/null
+++ b/src/Markup/Perspex.Markup/FuncValueConverter.cs
@@ -0,0 +1,48 @@
+// Copyright (c) The Perspex Project. All rights reserved.
+// Licensed under the MIT license. See licence.md file in the project root for full license information.
+
+using System;
+using System.Globalization;
+using Perspex.Utilities;
+
+namespace Perspex.Markup
+{
+ ///
+ /// A general purpose that uses a
+ /// to provide the converter logic.
+ ///
+ ///
+ ///
+ public class FuncValueConverter : IValueConverter
+ {
+ private Func _convert;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The convert function.
+ public FuncValueConverter(Func convert)
+ {
+ _convert = convert;
+ }
+
+ ///
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ if (value is TIn || (value == null && TypeUtilities.AcceptsNull(typeof(TIn))))
+ {
+ return _convert((TIn)value);
+ }
+ else
+ {
+ return PerspexProperty.UnsetValue;
+ }
+ }
+
+ ///
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/src/Markup/Perspex.Markup/Perspex.Markup.csproj b/src/Markup/Perspex.Markup/Perspex.Markup.csproj
index 0aa2af5df3..702f3f9a82 100644
--- a/src/Markup/Perspex.Markup/Perspex.Markup.csproj
+++ b/src/Markup/Perspex.Markup/Perspex.Markup.csproj
@@ -36,6 +36,9 @@
bin\Release\Perspex.Markup.XML
+
+ Properties\SharedAssemblyInfo.cs
+
@@ -49,6 +52,8 @@
+
+
diff --git a/src/Markup/Perspex.Markup/Properties/AssemblyInfo.cs b/src/Markup/Perspex.Markup/Properties/AssemblyInfo.cs
index 9076f81754..f3387d7682 100644
--- a/src/Markup/Perspex.Markup/Properties/AssemblyInfo.cs
+++ b/src/Markup/Perspex.Markup/Properties/AssemblyInfo.cs
@@ -1,32 +1,10 @@
-using System.Resources;
+// Copyright (c) The Perspex Project. All rights reserved.
+// Licensed under the MIT license. See licence.md file in the project root for full license information.
+
using System.Reflection;
+using Perspex.Metadata;
using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-// General Information about an assembly is controlled through the following
-// set of attributes. Change these attribute values to modify the information
-// associated with an assembly.
[assembly: AssemblyTitle("Perspex.Markup")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("Perspex.Markup")]
-[assembly: AssemblyCopyright("Copyright © 2015")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-[assembly: NeutralResourcesLanguage("en")]
-
-// Version information for an assembly consists of the following four values:
-//
-// Major Version
-// Minor Version
-// Build Number
-// Revision
-//
-// You can specify all the values or you can default the Build and Revision Numbers
-// by using the '*' as shown below:
-// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyFileVersion("1.0.0.0")]
-
+[assembly: XmlnsDefinition("https://github.com/perspex", "Perspex.Markup")]
[assembly: InternalsVisibleTo("Perspex.Markup.UnitTests")]
\ No newline at end of file
diff --git a/src/Markup/Perspex.Markup/StringConverters.cs b/src/Markup/Perspex.Markup/StringConverters.cs
new file mode 100644
index 0000000000..3cc3c68b9f
--- /dev/null
+++ b/src/Markup/Perspex.Markup/StringConverters.cs
@@ -0,0 +1,21 @@
+// Copyright (c) The Perspex Project. All rights reserved.
+// Licensed under the MIT license. See licence.md file in the project root for full license information.
+
+using System;
+using System.Globalization;
+using Perspex.Utilities;
+
+namespace Perspex.Markup
+{
+ ///
+ /// Provides a set of useful s for working with string values.
+ ///
+ public static class StringConverters
+ {
+ ///
+ /// A value converter that returns true if the input string is null or an empty string.
+ ///
+ public static readonly IValueConverter NullOrEmpty =
+ new FuncValueConverter(x => string.IsNullOrEmpty(x));
+ }
+}
diff --git a/src/Perspex.Base/Utilities/TypeUtilities.cs b/src/Perspex.Base/Utilities/TypeUtilities.cs
index 02db883e08..d9186afbb5 100644
--- a/src/Perspex.Base/Utilities/TypeUtilities.cs
+++ b/src/Perspex.Base/Utilities/TypeUtilities.cs
@@ -27,6 +27,17 @@ namespace Perspex.Utilities
{ typeof(short), new List { typeof(byte) } }
};
+ ///
+ /// Returns a value indicating whether null can be assigned to the specified type.
+ ///
+ /// The type.
+ /// True if the type accepts null values; otherwise false.
+ public static bool AcceptsNull(Type type)
+ {
+ var t = type.GetTypeInfo();
+ return !t.IsValueType || (t.IsGenericType && (t.GetGenericTypeDefinition() == typeof(Nullable<>)));
+ }
+
///
/// Try to cast a value to a type, using implicit conversions if possible.
///
@@ -40,9 +51,8 @@ namespace Perspex.Utilities
if (value == null)
{
- var t = to.GetTypeInfo();
result = null;
- return !t.IsValueType || (t.IsGenericType && (t.GetGenericTypeDefinition() == typeof(Nullable<>)));
+ return AcceptsNull(to);
}
var from = value.GetType();