Skip to content
This repository has been archived by the owner on May 1, 2024. It is now read-only.

Add DataTemplate extensions to allow typesafe binding just like BindableObject #232

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
27 changes: 27 additions & 0 deletions Xamarin.Forms.Core.UnitTests/DataTemplateExtensionTests.cs
@@ -0,0 +1,27 @@
using System;
using NUnit.Framework;

namespace Xamarin.Forms.Core.UnitTests
{
[TestFixture]
public class DataTemplateExtensionTests : BaseTestFixture
{
[Test]
public void SetBindingNull()
{
Assert.That(() => TemplateExtensions.SetBinding(null, MockBindable.TextProperty, "Name"),
Throws.InstanceOf<ArgumentNullException>());
Assert.That(() => TemplateExtensions.SetBinding(new DataTemplate(() => new MockBindable()), null, "Name"),
Throws.InstanceOf<ArgumentNullException>());
Assert.That(() => TemplateExtensions.SetBinding(new DataTemplate(() => new MockBindable()), MockBindable.TextProperty, null),
Throws.InstanceOf<ArgumentNullException>());

Assert.That(() => TemplateExtensions.SetBinding<MockViewModel>(null, MockBindable.TextProperty, vm => vm.Text),
Throws.InstanceOf<ArgumentNullException>());
Assert.That(() => TemplateExtensions.SetBinding<MockViewModel>(new DataTemplate(() => new MockBindable()), null, vm => vm.Text),
Throws.InstanceOf<ArgumentNullException>());
Assert.That(() => TemplateExtensions.SetBinding<MockViewModel>(new DataTemplate(() => new MockBindable()), MockBindable.TextProperty, null),
Throws.InstanceOf<ArgumentNullException>());
}
}
}
Expand Up @@ -176,6 +176,7 @@
<Compile Include="TriggerTests.cs" />
<Compile Include="PinchGestureRecognizerTests.cs" />
<Compile Include="AppLinkEntryTests.cs" />
<Compile Include="DataTemplateExtensionTests.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Xamarin.Forms.Core\Xamarin.Forms.Core.csproj">
Expand Down
3 changes: 1 addition & 2 deletions Xamarin.Forms.Core/DataTemplateExtensions.cs
Expand Up @@ -5,8 +5,7 @@ internal static class DataTemplateExtensions
public static object CreateContent(this DataTemplate self, object item, BindableObject container)
{
var selector = self as DataTemplateSelector;
if (selector != null)
{
if (selector != null) {
self = selector.SelectTemplate(item, container);
}
return self.CreateContent();
Expand Down
23 changes: 21 additions & 2 deletions Xamarin.Forms.Core/TemplateExtensions.cs
@@ -1,15 +1,34 @@
using System;
using System.Linq.Expressions;

namespace Xamarin.Forms
{
public static class TemplateExtensions
{
public static void SetBinding(this DataTemplate self, BindableProperty targetProperty, string path)
public static void SetBinding(this DataTemplate self, BindableProperty targetProperty, string path, BindingMode mode = BindingMode.Default, IValueConverter converter = null,
string stringFormat = null)
{
if (self == null)
throw new ArgumentNullException("self");
if (targetProperty == null)
throw new ArgumentNullException("targetProperty");

self.SetBinding(targetProperty, new Binding(path));
var binding = new Binding(path, mode, converter, stringFormat: stringFormat);
self.SetBinding(targetProperty, binding);
}

public static void SetBinding<TSource>(this DataTemplate self, BindableProperty targetProperty, Expression<Func<TSource, object>> sourceProperty, BindingMode mode = BindingMode.Default,
IValueConverter converter = null, string stringFormat = null)
{
if (self == null)
throw new ArgumentNullException("self");
if (targetProperty == null)
throw new ArgumentNullException("targetProperty");
if (sourceProperty == null)
throw new ArgumentNullException("sourceProperty");

Binding binding = Binding.Create(sourceProperty, mode, converter, stringFormat: stringFormat);
self.SetBinding(targetProperty, binding);
}
}
}
86 changes: 71 additions & 15 deletions docs/Xamarin.Forms.Core/Xamarin.Forms/TemplateExtensions.xml
Expand Up @@ -16,21 +16,15 @@
</Base>
<Interfaces />
<Docs>
<summary>Extension class for DataTemplate, providing a string-based shortcut method for defining a Binding.</summary>
<remarks>To be added.</remarks>
<summary>Contains convenience extension methods for <see cref="T:Xamarin.Forms.DataTemplate" />.</summary>
<remarks></remarks>
</Docs>
<Members>
<Member MemberName="SetBinding">
<MemberSignature Language="C#" Value="public static void SetBinding (this Xamarin.Forms.DataTemplate self, Xamarin.Forms.BindableProperty targetProperty, string path);" />
<MemberSignature Language="ILAsm" Value=".method public static hidebysig void SetBinding(class Xamarin.Forms.DataTemplate self, class Xamarin.Forms.BindableProperty targetProperty, string path) cil managed" />
<MemberSignature Language="C#" Value="public static void SetBinding (this Xamarin.Forms.DataTemplate self, Xamarin.Forms.BindableProperty targetProperty, string path, Xamarin.Forms.BindingMode mode = Xamarin.Forms.BindingMode.Default, Xamarin.Forms.IValueConverter converter = null, string stringFormat = null);" />
<MemberSignature Language="ILAsm" Value=".method public static hidebysig void SetBinding(class Xamarin.Forms.DataTemplate self, class Xamarin.Forms.BindableProperty targetProperty, string path, valuetype Xamarin.Forms.BindingMode mode, class Xamarin.Forms.IValueConverter converter, string stringFormat) cil managed" />
<MemberType>Method</MemberType>
<AssemblyInfo>
<AssemblyVersion>1.0.0.0</AssemblyVersion>
<AssemblyVersion>1.1.0.0</AssemblyVersion>
<AssemblyVersion>1.2.0.0</AssemblyVersion>
<AssemblyVersion>1.3.0.0</AssemblyVersion>
<AssemblyVersion>1.4.0.0</AssemblyVersion>
<AssemblyVersion>1.5.0.0</AssemblyVersion>
<AssemblyVersion>2.0.0.0</AssemblyVersion>
</AssemblyInfo>
<ReturnValue>
Expand All @@ -40,13 +34,75 @@
<Parameter Name="self" Type="Xamarin.Forms.DataTemplate" RefType="this" />
<Parameter Name="targetProperty" Type="Xamarin.Forms.BindableProperty" />
<Parameter Name="path" Type="System.String" />
<Parameter Name="mode" Type="Xamarin.Forms.BindingMode" />
<Parameter Name="converter" Type="Xamarin.Forms.IValueConverter" />
<Parameter Name="stringFormat" Type="System.String" />
</Parameters>
<Docs>
<param name="self">To be added.</param>
<param name="targetProperty">To be added.</param>
<param name="path">To be added.</param>
<summary>Binds the <paramref name="self" /> object's <paramref name="targetProperty" /> to a new <see cref="T:Xamarin.Forms.Binding" /> instance that was created with <paramref name="path" />.</summary>
<remarks>To be added.</remarks>
<param name="self">The <see cref="T:Xamarin.Forms.DataTemplate" />.</param>
<param name="targetProperty">The BindableProperty on which to set a binding.</param>
<param name="path">A <see cref="T:System.String" /> indicating the property path to bind to.</param>
<param name="mode">The <see cref="T:Xamarin.Forms.BindingMode" /> for the binding. This parameter is optional. Default is <see cref="E:Xamarin.Forms.BindingMode.Default" />.</param>
<param name="converter">An <see cref="T:Xamarin.Forms.IValueConverter" /> for the binding. This parameter is optional. Default is <see langword="null" />.</param>
<param name="stringFormat">A string used as stringFormat for the binding. This parameter is optional. Default is <see langword="null" />.</param>
<summary>Creates and applies a binding to a property.</summary>
<remarks>
<para>The following example shows how to use the extension method to set a binding.</para>
<example>
<code lang="C#"><![CDATA[
var itemTemplate = new DataTemplate(typeof(TextCell));
itemTemplate.SetBinding (TextCell.TextProperty, "Name");
]]></code>
</example>
</remarks>
</Docs>
</Member>
<Member MemberName="SetBinding&lt;TSource&gt;">
<MemberSignature Language="C#" Value="public static void SetBinding&lt;TSource&gt; (this Xamarin.Forms.DataTemplate self, Xamarin.Forms.BindableProperty targetProperty, System.Linq.Expressions.Expression&lt;Func&lt;TSource,object&gt;&gt; sourceProperty, Xamarin.Forms.BindingMode mode = Xamarin.Forms.BindingMode.Default, Xamarin.Forms.IValueConverter converter = null, string stringFormat = null);" />
<MemberSignature Language="ILAsm" Value=".method public static hidebysig void SetBinding&lt;TSource&gt;(class Xamarin.Forms.DataTemplate self, class Xamarin.Forms.BindableProperty targetProperty, class System.Linq.Expressions.Expression`1&lt;class System.Func`2&lt;!!TSource, object&gt;&gt; sourceProperty, valuetype Xamarin.Forms.BindingMode mode, class Xamarin.Forms.IValueConverter converter, string stringFormat) cil managed" />
<MemberType>Method</MemberType>
<AssemblyInfo>
<AssemblyVersion>2.0.0.0</AssemblyVersion>
</AssemblyInfo>
<ReturnValue>
<ReturnType>System.Void</ReturnType>
</ReturnValue>
<TypeParameters>
<TypeParameter Name="TSource" />
</TypeParameters>
<Parameters>
<Parameter Name="self" Type="Xamarin.Forms.DataTemplate" RefType="this" />
<Parameter Name="targetProperty" Type="Xamarin.Forms.BindableProperty" />
<Parameter Name="sourceProperty" Type="System.Linq.Expressions.Expression&lt;System.Func&lt;TSource,System.Object&gt;&gt;" />
<Parameter Name="mode" Type="Xamarin.Forms.BindingMode" />
<Parameter Name="converter" Type="Xamarin.Forms.IValueConverter" />
<Parameter Name="stringFormat" Type="System.String" />
</Parameters>
<Docs>
<typeparam name="TSource">The source type.</typeparam>
<param name="self">The DataTemplate.</param>
<param name="targetProperty">The BindableProperty to bind to</param>
<param name="sourceProperty">An expression used to retrieve the source path.</param>
<param name="mode">The BindingMode for the binding. This parameter is optional. Default is <see cref="E:Xamarin.Forms.BindingMode.Default" />.</param>
<param name="converter">An IValueConverter for the binding. This parameter is optional. Default is <see langword="null" />.</param>
<param name="stringFormat">A string used as stringFormat for the binding. This parameter is optional. Default is <see langword="null" />.</param>
<summary>Creates and applies a binding from an expression.</summary>
<remarks>
<para>This extension method uses Expression instead of path to creates and sets bindings. Using Expressions is more refactoring friendly.</para>
<para>This following example illustrates the setting of a binding using the extension method.</para>
<example>
<code lang="C#"><![CDATA[
public class PersonViewModel
{
public string Name { get; set; }
public string Company { get; set; }
}

var itemTemplate = new DataTemplate(typeof(TextCell));
itemTemplate.SetBinding<PersonViewModel> (TextCell.TextProperty, vm => vm.Name);
]]></code>
</example>
</remarks>
</Docs>
</Member>
</Members>
Expand Down