Skip to content

Commit 1fab97a

Browse files
Merge pull request #1 from Yeah69/master
Extension of the lambda-converters to support DataTemplateSelectors and ValidationRules
2 parents be0a05a + f741a5c commit 1fab97a

15 files changed

+762
-1
lines changed

README.md

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,84 @@ You're done! Just reference the converters with the `x:Static` expressions from
3636

3737
:bulb: *ReSharper users*: use the Extension Manager to install the external annotations for the library.
3838

39+
## Lambda DataTemplateSelectors
40+
41+
The library also allows to create `DataTemplateSelector` objects in the same convenient way as Converters. In order to define a Selector simply write a static field (or property) similar to this snippet:
42+
43+
```csharp
44+
internal static class TemplateSelector
45+
{
46+
public static DataTemplateSelector AlternatingText =
47+
LambdaConverters.TemplateSelector.Create<int>(
48+
e => e.Item % 2 == 0
49+
? (DataTemplate) ((FrameworkElement) e.Container)?.FindResource("BlackWhite")
50+
: (DataTemplate) ((FrameworkElement) e.Container)?.FindResource("WhiteBlack"));
51+
}
52+
```
53+
Use your Lambda DataTemplateSelectors by referencing it with the `x:Static` markup extention:
54+
55+
```xml
56+
<UserControl.Resources>
57+
<DataTemplate x:Key="BlackWhite">
58+
<TextBlock Text="{Binding}"
59+
Foreground="Black"
60+
Background="White" />
61+
</DataTemplate>
62+
<DataTemplate x:Key="WhiteBlack">
63+
<TextBlock Text="{Binding}"
64+
Foreground="White"
65+
Background="Black" />
66+
</DataTemplate>
67+
</UserControl.Resources>
68+
<DockPanel>
69+
<ListBox ItemsSource="{Binding IntNumbers}"
70+
ItemTemplateSelector="{x:Static s:TemplateSelector.AlternatingText}">
71+
</ListBox>
72+
</DockPanel>
73+
```
74+
75+
Tada! All even numbers from `IntNumbers` are displayed with black font and white background and the odd numbers get the inverse font and background colors.
76+
77+
### Features
78+
- *strongly-typed* Selectors
79+
- resource declaration not needed, just use the `x:Static` expressions
80+
- separate class for each selector not needed anymore
81+
- full support for the remaining parameter `container`. For example, if you need to grab a `DataTemplate` from where the selector is use (see the example above).
82+
83+
## Lambda ValidationRules
84+
85+
Furthermore, you'll get Lambda ValidationRules on top. By now you know "the drill". First, define a `ValidationRule`object like this:
86+
87+
```csharp
88+
public static class Rule
89+
{
90+
public static ValidationRule IsNumericString =
91+
LambdaConverters.Validator.Create<string>(
92+
e => e.Value.ToCharArray().All(char.IsDigit)
93+
? ValidationResult.ValidResult
94+
: new ValidationResult(false, "Text has non-digit characters!"));
95+
}
96+
```
97+
And then reference your new rule in vour `View`:
98+
```xml
99+
<TextBox>
100+
<TextBox.Text>
101+
<Binding Path="Text" UpdateSourceTrigger="PropertyChanged">
102+
<Binding.ValidationRules>
103+
<x:Static Member="r:Rule.IsNumericString"/>
104+
</Binding.ValidationRules>
105+
</Binding>
106+
</TextBox.Text>
107+
</TextBox>
108+
```
109+
Now, you made sure that only strings which consists of digits are passed to your `ViewModel`.
110+
111+
### Features
112+
- *strongly-typed* rules
113+
- resource declaration not needed, just use the `x:Static` expressions
114+
- separate class for each rule not needed anymore
115+
- full support for the remaining parameter `culture`
116+
39117
## Installation
40118
Use the NuGet package manager to install the package.
41119

Sources/LambdaConverters.Wpf/EventSource.cs

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ internal sealed class EventSource : System.Diagnostics.Tracing.EventSource
1313
public static class Keywords
1414
{
1515
public const EventKeywords Converters = (EventKeywords)0x4;
16+
public const EventKeywords Selectors = (EventKeywords)0x8;
17+
public const EventKeywords Rules = (EventKeywords)0x10;
1618
}
1719

1820
[NotNull]
@@ -451,5 +453,121 @@ public void UnableToCastToParameterTypeForBackConversion(
451453
memberName,
452454
sourceFilePath,
453455
sourceLineNumber);
456+
457+
/// <summary>
458+
/// The {0} is null, conversion result is a value according to the specified error strategy ({1}).
459+
/// </summary>
460+
[Conditional("TRACE")]
461+
[Event(
462+
22,
463+
Version = 0,
464+
Message = "The {0} is null, conversion result is a value according to the specified error strategy ({1}).",
465+
Level = EventLevel.Warning,
466+
Keywords = Keywords.Selectors,
467+
Opcode = EventOpcode.Info,
468+
Channel = EventChannel.Operational
469+
)]
470+
public void MissingSelectTemplateFunction(
471+
string callback,
472+
string errorStrategy,
473+
[CallerMemberName] string memberName = null,
474+
[CallerFilePath] string sourceFilePath = null,
475+
[CallerLineNumber] int sourceLineNumber = 0)
476+
=>
477+
WriteEvent(
478+
22,
479+
callback,
480+
errorStrategy,
481+
memberName,
482+
sourceFilePath,
483+
sourceLineNumber);
484+
485+
/// <summary>
486+
/// The value ({0}) cannot be cast to the specified input type ({1}), conversion result is a value according to the specified error strategy ({2}).
487+
/// </summary>
488+
[Conditional("TRACE")]
489+
[Event(
490+
23,
491+
Version = 0,
492+
Message = "The value ({0}) cannot be cast to the specified input type ({1}), conversion result is a value according to the specified error strategy ({2}).",
493+
Level = EventLevel.Warning,
494+
Keywords = Keywords.Selectors,
495+
Opcode = EventOpcode.Info,
496+
Channel = EventChannel.Operational
497+
)]
498+
public void UnableToCastToItemType(
499+
string itemType,
500+
string inputType,
501+
string errorStrategy,
502+
[CallerMemberName] string memberName = null,
503+
[CallerFilePath] string sourceFilePath = null,
504+
[CallerLineNumber] int sourceLineNumber = 0)
505+
=>
506+
WriteEvent(
507+
23,
508+
itemType,
509+
inputType,
510+
errorStrategy,
511+
memberName,
512+
sourceFilePath,
513+
sourceLineNumber);
514+
515+
/// <summary>
516+
/// The {0} is null, conversion result is a value according to the specified error strategy ({1}).
517+
/// </summary>
518+
[Conditional("TRACE")]
519+
[Event(
520+
24,
521+
Version = 0,
522+
Message = "The {0} is null, conversion result is a value according to the specified error strategy ({1}).",
523+
Level = EventLevel.Warning,
524+
Keywords = Keywords.Rules,
525+
Opcode = EventOpcode.Info,
526+
Channel = EventChannel.Operational
527+
)]
528+
public void MissingRuleFunction(
529+
string callback,
530+
string errorStrategy,
531+
[CallerMemberName] string memberName = null,
532+
[CallerFilePath] string sourceFilePath = null,
533+
[CallerLineNumber] int sourceLineNumber = 0)
534+
=>
535+
WriteEvent(
536+
24,
537+
callback,
538+
errorStrategy,
539+
memberName,
540+
sourceFilePath,
541+
sourceLineNumber);
542+
543+
/// <summary>
544+
/// The value ({0}) cannot be cast to the specified input type ({1}), conversion result is a value according to the specified error strategy ({2}).
545+
/// </summary>
546+
[Conditional("TRACE")]
547+
[Event(
548+
25,
549+
Version = 0,
550+
Message = "The value ({0}) cannot be cast to the specified input type ({1}), conversion result is a value according to the specified error strategy ({2}).",
551+
Level = EventLevel.Warning,
552+
Keywords = Keywords.Rules,
553+
Opcode = EventOpcode.Info,
554+
Channel = EventChannel.Operational
555+
)]
556+
public void UnableToCastToRuleInputType(
557+
string itemType,
558+
string inputType,
559+
string errorStrategy,
560+
[CallerMemberName] string memberName = null,
561+
[CallerFilePath] string sourceFilePath = null,
562+
[CallerLineNumber] int sourceLineNumber = 0)
563+
=>
564+
WriteEvent(
565+
25,
566+
itemType,
567+
inputType,
568+
errorStrategy,
569+
memberName,
570+
sourceFilePath,
571+
sourceLineNumber);
454572
}
455573
}

Sources/LambdaConverters.Wpf/LambdaConverters.Wpf.csproj

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@
5858
</ItemGroup>
5959
<ItemGroup>
6060
<Compile Include="Converter.cs" />
61+
<Compile Include="RuleErrorStrategy.cs" />
62+
<Compile Include="SelectorErrorStrategy.cs" />
6163
<Compile Include="ConverterErrorStrategy.cs" />
6264
<Compile Include="EventSource.cs" />
6365
<Compile Include="MultiValueConverter.cs" />
@@ -66,10 +68,16 @@
6668
<Compile Include="MultiValueConverterArgs[T].cs" />
6769
<Compile Include="MultiValueConverterArgs[T].IEquatable[MultiValueConverterArgs[T]].cs" />
6870
<Compile Include="Properties\AssemblyInfo.cs" />
71+
<Compile Include="Validator.cs" />
72+
<Compile Include="TemplateSelector.cs" />
6973
<Compile Include="ValueConverter.cs" />
74+
<Compile Include="ValidationRuleArgs[T].cs" />
7075
<Compile Include="ValueConverterArgs[T,P].cs" />
7176
<Compile Include="ValueConverterArgs[T,P].IEquatable[ValueConverterArgs[T,P]].cs" />
77+
<Compile Include="TemplateSelectorArgs[T].cs" />
7278
<Compile Include="ValueConverterArgs[T].cs" />
79+
<Compile Include="TemplateSelectorArgs[T].IEquatable[TemplateSelectorArgs[T]].cs" />
80+
<Compile Include="ValidationRuleArgs[T].IEquatable[ValidationRuleArgs[T]].cs" />
7381
<Compile Include="ValueConverterArgs[T].IEquatable[ValueConverterArgs[T]].cs" />
7482
</ItemGroup>
7583
<ItemGroup>

Sources/LambdaConverters.Wpf/Properties/AssemblyInfo.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
[assembly: AssemblyConfiguration("")]
1010
[assembly: AssemblyCompany("")]
1111
[assembly: AssemblyProduct("LambdaConverters")]
12-
[assembly: AssemblyCopyright(2016 Michael Damatov.")]
12+
[assembly: AssemblyCopyright(2017 Michael Damatov, Dimitri Enns.")]
1313
[assembly: AssemblyTrademark("")]
1414
[assembly: AssemblyCulture("")]
1515

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
using System.Windows.Controls;
2+
3+
namespace LambdaConverters
4+
{
5+
/// <summary>
6+
/// Defines the validation rule error strategy.
7+
/// </summary>
8+
public enum RuleErrorStrategy
9+
{
10+
/// <summary>
11+
/// Null is returned.
12+
/// </summary>
13+
ReturnNull,
14+
15+
/// <summary>
16+
/// An invalid validation result is returned.
17+
/// </summary>
18+
ReturnInvalid,
19+
20+
/// <summary>
21+
/// A valid validation result is returned.
22+
/// </summary>
23+
ReturnValid
24+
}
25+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
namespace LambdaConverters
2+
{
3+
/// <summary>
4+
/// Defines the selector error strategy.
5+
/// </summary>
6+
public enum SelectorErrorStrategy
7+
{
8+
/// <summary>
9+
/// Null is returned.
10+
/// </summary>
11+
ReturnNull,
12+
13+
/// <summary>
14+
/// A new and empty data template is returned.
15+
/// </summary>
16+
ReturnNewEmptyDataTemplate
17+
}
18+
}

0 commit comments

Comments
 (0)