futurice/uwp-reusables

Name: uwp-reusables

Owner: Futurice

Description: A library of controls and logic that get reused frequently.

Created: 2016-01-18 15:54:59.0

Updated: 2016-03-08 13:46:37.0

Pushed: 2016-06-16 13:20:37.0

Homepage:

Size: 118

Language: C#

GitHub Committers

UserMost Recent Commit# Commits

Other Committers

UserEmailMost Recent Commit# Commits

README

UWP Reusables

A collection of logic and controls that are generically useful for any UWP project.

Current status: Not ready for release

What needs to be done?

Controls
ValidatingTextBox

Animated example

A text box that validates all input, and displays error messages if any of the validation functions fail.

Can be used in XAML:

tb:ValidatingTextBox PlaceholderText="No dots or exclamations allowed.">
        <vtb:ValidationPair ErrorMessage="No dots allowed." ValidationFunction="{x:Bind NoDotsFunction}"/>
        <vtb:ValidationPair ErrorMessage="Exclamation marks not allowed either >:|" ValidationFunction="{x:Bind NoExclamationsFunction}"/>
tb:ValidatingTextBox>

and the validation functions bound to are simply defined in code-behind as follows:

ic Func<string, bool> NoDotsFunction { get; set; } = NoDotsFunctionImpl;
ic Func<string, bool> NoExclamationsFunction { get; set; } = NoExclamationsImpl;

ate static bool NoDotsFunctionImpl(string input)

if (input.Contains("."))
{
    return false;
}
else
{
    return true;
}


ate static bool NoExclamationsImpl(string arg)

if (arg.Contains("!"))
{
    return false;
}
else
{
    return true;
}

Note that the validation functions are pure, static functions, and could be defined anywhere; your ViewModel, a PCL, whatever.

Can also be defined in code-behind:

ng locallyScopedString = "closures work just fine";
datingTextBox codeBehindBox = new ValidatingTextBox();
BehindBox.ValidationPairs.Add(new ValidationPair

ValidationFunction = s => s.Contains("@"),
ErrorMessage = $"Gotta have at least one @ here. And {locallyScopedString}!",                
  
ValidatingTextBoxPortable

The portable version of the above ValidatingTextBox. This sacrifices usability in favor of portability. The ValidatingTextBox requires that any part of the program that defines validation functions know about the ValidationPair class, and requires a reference to the ValidatingTextBox project. The ValidatingTextBoxPortable, however, allows validating functions to be defined without needing that reference. The tradeoff is that the syntax is slightly less friendly.

In XAML:

idation:ValidatingTextBoxPortable PlaceholderText="No dots or exclamations" 
                                  ValidationFunctions="{x:Bind TopBoxValidationFunctions}">

And the TopBoxValidationFunctions is an IList<Func<string, string>>–that is, a List of Functions that take in a string as input, and return a string. It might be defined as follows:

ic IList<Func<string, string>> TopBoxValidationFunctions => new List<Func<string, string>>

input => input.Contains("!") ? "No shouting! Exclamations aren't allowed." : null,
input => input.Contains(".") ? "Can't be having none of them dots, either." : null

…and those validation functions treat null return values as validation successes, and non-null values are treated as validation failures, with the returned string being interpreted as the error message for that validation function.

InlineFormatter

The InlineFormatter attached propertes allow binding formatted text strings (e.g. "<format>This <bold>text</bold> <underline>has</underline> <italic>formatting</italic>!</format>") as XAML TextBlock content. The feature is implemented by parsing the input string using the platform XML parser and assigning the resulting Inline tree to TextBlock.Inlines.

You might be asking what is the point of such behaviour: in XAML, we can always anyway construct the corresponding Inline tree in code and directly assign it to the target TextBlock. Well, this might be a good idea as long as you never have to localize your app. However, as soon as you start sourcing your UI strings from a localization file, you will most definitely want to specify the logical structure of the formatting in your translated strings. This is not possible by using vanilla bindings, because you can't do anything like <TextBlock Inlines="{x:Bind MyLocalizedFormatString}" /> (<TextBlock Text="{x:Bind MyLocalizedSimpleString}" /> works, because Text expects a string).

The formatting can be anything supported by XAML Inlines, and you can define your own custom formatter in code, including adding inline links with arbirtrary click handlers. The default formatter only supports mapping the Bold, Underline and Italic tags 1:1. See the TestBed for examples.

This code was inspired by and improved from http://stackoverflow.com/questions/5565885/how-to-bind-a-textblock-to-a-resource-containing-formatted-text


This work is supported by the National Institutes of Health's National Center for Advancing Translational Sciences, Grant Number U24TR002306. This work is solely the responsibility of the creators and does not necessarily represent the official views of the National Institutes of Health.