Code Monkey home page Code Monkey logo

calcbinding's Introduction

CalcBinding

CalcBinding is an advanced Binding markup extension that allows you to write calculated binding expressions in xaml, without custom converters. CalcBinding can automaticaly perfom bool to visibility convertion, different algebraic operations, inverse your expression and more. CalcBinding makes binding expressions shorter and more user-friendly. Release notes

Install

CalcBinding is available at NuGet. You can install package using:

PM> Install-Package CalcBinding 

Overview

Following example shows xaml snippets with standart Binding and with CalcBinding in very simple case:

Before:

<Label>
  <Label.Content>
  <MultiBinding Conveter={x:StaticResource MyCustomConverter}> 
    <Binding A/> 
    <Binding B/> 
    <Binding C/> 
  </MultiBinding>
  </Label.Content>
</Label> 

(without MyCustomConveter declaration and referencing to it in xaml)

After:

<Label Content="{c:Binding A+B+C }" />

Key features and restrictions:

  1. One or many source properties in Path with many available operators: description
<Label Content="{c:Binding A*0.5+(B.NestedProp1/C - B.NestedProp2 % C) }" />
<c:Binding 'A and B or C' />
  1. One or many static properties in Path: description
<TextBox Text="{c:Binding 'local:StaticClass.Prop1 + local:OtherStaticClass.NestedProp.PropB + PropC'}"/>
<Button Background="{c:Binding '(A > B ? media:Brushes.LightBlue : media:Brushes.White)'}"/>
  1. Properties and methods of class System.Math in Path: description
<TextBox Text="{c:Binding 'Math.Sin(Math.Cos(A))'}"/>
  1. Enum types like constants or source properties in Path: description
<TextBox Text="{c:Binding '(EnumValue == local:CustomEnum.Value1 ? 10 : 20)'}"/>
  1. Automatic inversion of binding expression if it's possible: description
<TextBox Text = "{c:Binding 'Math.Sin(A*2)-5'}"/> {two way binding will be created}
  1. Automatic two way convertion of bool expression to Visibility and back if target property has such type: description
<Button Visibility="{c:Binding !IsChecked}" /> 
<Button Visibility="{c:Binding IsChecked, FalseToVisibility=Hidden}" />
  1. Other features such as string and char constants support and other: description

  2. General restrictions: description

Documentation

1. Source properties and operators

You can write any algebraic, logical and string expressions, that contain source property pathes, strings, digits, all members of class Math and following operators:

"(", ")", "+", "-", "*", "/", "%", "^", "!", "&&","||",
"&", "|", "?", ":", "<", ">", "<=", ">=", "==", "!="};

and ternary operator in form of 'bool_expression ? expression_1 : expression_2'

One should know, that xaml is generally xml format, and xml doesn't support using of following symbols when setting attribute value: &, <. Therefore, CalcBinding supports following aliases for operators that contain these symbols:

operator alias comment
&& and
|| or not nessesary, just for symmetry
< less
<= less=

Examples

Algebraic

<TextBox Text="{c:Binding A+B+C}"/>
<TextBox Text="{c:Binding A-B-C}"/>
<TextBox Text="{c:Binding A*(B+C)}"/>
<TextBox Text="{c:Binding 2*A-B*0.5}"/>
<TextBox Text="{c:Binding A/B, StringFormat={}{0:n2} --StringFormat is used}"/> {with string format}
<TextBox Text="{c:Binding A%B}"/>
<TextBox Text="{c:Binding '(A == 1) ? 10 : 20'}"/> {ternary operator}

Logic

<CheckBox Content="!IsChecked" IsChecked="{c:Binding !IsChecked}"/>
<TextBox Text="{c:Binding 'IsChecked and IsFull'}"/> {'and' is equvalent of '&&'}
<TextBox Text="{c:Binding '!IsChecked or (A > B)'}"/> {'or' is equvalent of '||', but you can leave '||'}
<TextBox Text="{c:Binding '(A == 1) and (B less= 5)'}"/> {'less=' is equvalent of '<='}
<TextBox Text="{c:Binding (IsChecked || !IsFull)}"/>

Restrictions:

  1. Identifiers that make up the source property path, should be separated from operator ':' by any operator or delimititer (single quote, space etc.) in ternary operator:

right:

<TextBox Text="{c:Binding '(A == 2)?IsChecked : IsFull}"/> <!-- right -->
<TextBox Text="{c:Binding '(A == 2)?IsChecked :!IsFull}"/> <!-- right -->
<TextBox Text="{c:Binding '(A == 2) ? IsChecked :4 + IsFull}"/> <!-- right -->

wrong:

<TextBox Text="{c:Binding '(A == 2)?IsChecked:IsFull}"/> <!-- wrong -->

That restricition is caused by path analyzer work that finds static properties

2. Static properties

Beginning with version 2.3 CalcBinding supports static properties in binding expression. You can write pathes that begin with static property of any class and have any number of properties following behind static property. CalcBinding uses following syntax of static property path declaration:

'xmlNamespace:Class.StaticProperty.NestedProperty' etc.

where:

  1. xmlNamespace - usual xml namespace that is mapped to normal namespace in a header of xaml file with other namespaces definitions.

  2. Class - name of class that exists in namespace whereto xmlNamespace is mapped

  3. StaticProperty - static property of class Class

  4. .NestedProperty etc - chain of properties following behind StaticProperty

Examples:

<TextBox Text="{c:Binding 'local:Class.NestedProp.Prop1 + local:OtherStaticClass.PropB + PropC'}"/>
<Button Background="{c:Binding '(A > B ? media:Brushes.LightBlue : media:Brushes.White)'}"/>

where local and media are defined in a header of xaml file:

<<UserControl x:Class="WpfExample.FifthPage"
           xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
           xmlns:local="clr-namespace:WpfExample"
           xmlns:media ="clr-namespace:System.Windows.Media;assembly=PresentationCore">
   ...
</UserControl>

Restrictions

  1. As for non-static property pathes for static property pathes following rule is applied: you should put any delimiter or operator between ':' operator of ternary operator and identifiers (namespace or property) that make up static property path:

right:

<TextBox Text="{c:Binding '(A == 2)?local:Class.Prop1 : local:Class.Prop2}"/> <!-- right -->
<TextBox Text="{c:Binding '(A == 2)?local:OtherClass.IsChecked :!local.OtherClass.IsFull}"/> <!-- right -->
<TextBox Text="{c:Binding '(A == 2) ? local:Class.A :4 + local:Class.B}"/> <!-- right -->

wrong:

<TextBox Text="{c:Binding '(A == 2)?local:Class.Prop1: local:Class.Prop2}"/> <!-- wrong -->
<TextBox Text="{c:Binding '(A == 2)?local:OtherClass.IsChecked:local.OtherClass.IsFull}"/> <!-- wrong -->
<TextBox Text="{c:Binding '(A == 2) ? local:Class.A:4+local:Class.B}"/> <!-- wrong -->

3. Math class members

You can use in path property any members of System.Math class in native form as if you are writing usual C# code:

<TextBox Text="{c:Binding Math.Sin(A*Math.PI/180), StringFormat={}{0:n5}}"/>
<TextBox Text="{c:Binding A*Math.PI}" />

Restrictions

  1. Although CalcBinding supports static properties, Math class is a standalone feature that was created and used before static properties were supported. For this reason you shouldn't use static property syntax with members of Math class.

right:

<TextBox Text="{c:Binding A*Math.PI}" /> <!-- right -->
<TextBox Text="{c:Binding Math.Sin(10)+20}" /> <!-- right -->

wrong:

<xmlns:sys="clr-namespace:System;assembly=mscorlib">
...
<TextBox Text="{c:Binding A*sys:Math.PI}" /> <!-- wrong -->
<TextBox Text="{c:Binding sys:Math.Sin(10)+20}" /> <!-- wrong -->

4. Enums

Beginning with version 2.3 CalcBinding supports Enums expressions in binding expression. You can write enum values or properties that have Enum type (static properties too). CalcBinding uses following syntax of declaration enum value:

'xmlNamespace:EnumClass.Value'

where:

  1. xmlNamespace - usual xml namespace that is mapped to normal namespace in a header of xaml file with other namespaces definitions.

  2. EnumClass - name of enum class that exists in namespace whereto xmlNamespace is mapped

Examples:

<CheckBox Content="Started" IsChecked="{c:Binding 'State==local:StateEnum.Start'}" />
<Button Background="{c:Binding 'EnumValue == local:MyEnum.Value1 ? media:Brushes.Green : media:Brushes.Red'}"/>

where

  1. local and media are defined in a header of xaml file: xml <<UserControl x:Class="WpfExample.FifthPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:local="clr-namespace:WpfExample" xmlns:media ="clr-namespace:System.Windows.Media;assembly=PresentationCore"> ... </UserControl>

  2. StateEnum, MyEnum - custom Enums

  3. StateEnum.Start, MyEnum.Value1 - values of custom Enums

  4. Brushes - standart class with static Brush properties

  5. Brushes.Green, Brushes.Red - static properties of class Brushes

Restrictions

  1. As for static property pathes for Enum constants following rule is applied: you should put any delimiter or operator between ':' operator of ternary operator and identifiers (namespace or property) that make up Enum path:

right:

<TextBox Text="{c:Binding '(A == 2)?sys:Visibility.Visible : sys:Visibility.Hidden}"/> <!-- right -->
<TextBox Text="{c:Binding '(A == 2)?local:MyEnum.Value1 : local.MyEnum.Value2}"/> <!-- right -->

wrong:

<TextBox Text="{c:Binding '(A == 2)?sys:Visibility.Visible:sys:Visibility.Hidden}"/> <!-- wrong -->
<TextBox Text="{c:Binding '(A == 2)?local:MyEnum.Value1: local.MyEnum.Value2}"/> <!-- wrong -->
<TextBox Text="{c:Binding '(A == 2)?local:MyEnum.Value1 :local.MyEnum.Value2}"/> <!-- wrong -->

5. Automatic inversion of binding expression

For examle, you have to create two way binding from viewModel with double property A and Content property of TextBox. TextBox.Content depends on property 'A' by following formula: 'Math.Sin(A*2)-5'

All you have to do is to write:

<TextBox Text = "{c:Binding 'Math.Sin(A*2)-5'}">

CalcBinding recognizes that this expression has inversed expression 'A = Math.Asin(TextBox.Content + 2) / 2' and will use this expression for convertion dependency property TextBox.Text to property A of ViewModel when Text of textBox changes.

Previous expression equivalents to following usual code:

<TextBox Text = "{Binding Path=A, Conveter={x:StaticResource MyMathConverter}">
public class MyMathConverter : IValueConverter
{
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
          var source = (int)value;
          return Math.Sin(source*2)-5;
        }
        
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {        
          var res = Double.Parse(value);
          return (int)(Math.Asin(res + 5) / 2);
        }
}

Restrictions of creating inversed expression

  1. Binding must include only one property path (static or non-static) and only one entry of it

  2. Binding can contain only following operators and methods:

"+", "- (binary)", "*", "/", "Math.Sin", "Math.Cos", "Math.Tan", "Math.Asin", 
"Math.Acos", "Math.Atan","Math.Pow", "Math.Log", "!", "- (unary)"};

6. Bool to Visibility automatic convertion

CalcBinding recognizes if dependency property with Visibility type binds to bool expression. If it's true then bool expression is converted to Visibility automaticaly.

Obsiously true expression result is converted to Visibility.Visible

Property FalseToVisibility of CalcBinding specifies state in which false expression result is converted. Flag can have one of the following values:

  1. FalseToVisibility.Collapsed (default)
  2. FalseToFisibility.Hidden

Examples

<Button Content="TargetButton" Visibility="{c:Binding HasPrivileges, FalseToVisibility=Collapsed}"/>
or just
<Button Content="TargetButton" Visibility="{c:Binding !HasPrivileges}"/>

<Button Content="TargetButton" Visibility="{c:Binding !HasPrivileges, FalseToVisibility=Hidden}"/>

Automatic inversion is distributed to this convertion too. If dependency property equals to Visibility.Visible, then it's converted to true, otherwise - to false.

7. Other feautures

String, Char and SingleQuotes mode

Xaml is markup language based on xml language and xml doesn't support double-quotes signs in attribute values. Xaml doesn't support double-quotes too, futhermore it has problems with supporting single-quote character in Path value: in one expressions is works, in other - no. In order to give an opportunity of writing the most compact and readable string constants in the Path (\', or &apos; or &quot;) CalcBinding doesn't make difference between double and single quotes - all quotes are considered as double quotes by defaults. For example:

<TextBox Text="{c:Binding (Name + \' \' + Surname)}" />
<TextBox Text="{c:Binding (IsMan?\'Mr\':\'Ms\') + \' \' + Surname + \' \' + Name}"/>

However, in this case we loose the ability of supporting Char constants. Therefore beginning with version 2.3 CalcBinding has new property - SingleQuotes. If property is true, CalcBinding considers that all quotes - double and single, are single quotes. So \'A\' and &quot;A&quot; are Char symbols in that mode. If property is false, then single and double quotes are considered as double quotes, it is variant by defaults. So \'A\' and &quot;A&quot; are String constants in that mode. Examples of Char supporting:

<TextBox Text="{c:Binding 'Symbol == &quot;S&quot;?4:5', SingleQuotes=True}"/> {can't use no \' nor &apos; symbols because of xaml compiler generates error when parses == operator}

where Symbol - Char property.

Restrictions:

  1. Simultaneous using of Char and String constants is not supported in this version.

TemplateBinding

Althouth CalcBinding hasn't yet analog for TemplateBinding, as temporary solution you can write as follow:

<Button Content="Button" Width="100">
    <Button.Template>
        <ControlTemplate>
            <TextBox Width="{c:Binding Width+10, RelativeSource={RelativeSource TemplatedParent}}"/>
        </ControlTemplate>
    </Button.Template>
</Button> 

Setting RelativeSource property to TemplatedParent value makes CalcBinding similar to TemplateBinding

8. Tracing

All calcbinding traces are disabled by default due to huge amount of trace messages in some scenarios (see bug 44).

To enable traces, you need to specify minimal tracing level. Add this code to your app.config file to see all Information or higher priority logs:

  <system.diagnostics>
    <switches>
      <add name="CalcBindingTraceLevel" value="Information"/>
    </switches>
  </system.diagnostics>

Other available tracing levels:

  • All,
  • Off,
  • Critical,
  • Error,
  • Warning,
  • Information,
  • Verbose,

For more information, go to msdn: SourceSwitch

9. General restrictions

  1. Nullable value types doesn't supported in reverse binding (e.g. mode OneWayToSource)

  2. CalcBinding doesn't support your custom conveters at all now. If you need this feature, create new issue and put your using scenario in order to I can see that it is necessary

  3. In path expression you can't use any methods of .Net classes except of Math class.

What is inside?

CalcBinding uses DynamicExpresso library to parse string expression to Linq Expression and compiled expression tree for binding. DynamicExpresso is in fact a fork of DynamicLinq library, with many advantages and bug fixes compared with DynamicLinq (e.x. floating point parsing depending on CurrentCulture damn bug).

String expression is parsed only one time, when binding is initialized. In init section CalcBinding analyzer finds tokens in path expression: property path, static property path, Math expression and Enum expression. When binding is triggered first time, special binding converter replaces each property path and static propert path with variable of appropriate type and call DynamicExpresso to compile expression into delegate that takes new variables.

Working with the compiled expression increases speed of binding compared with parsing of string expression each time. On the development machine, these times are 0.03s for parsing each time and 0.001-0.003 s for working with the compiled expression

Notes

  1. Enum constants are using in expression for Dynamic Expresso directly, with collection of types of known Enums.
  2. Binding for collections (ListView, ListBox, DataGrid etc) are created as many times how many times it were declared in xaml. For example, if you have ListView with 10000 elements, and each element have template consisting of 5 controls which are all binded then only 5 Binding instances would be created.
  3. If one or more property pathes changes type of resulting property then compiling expression is recompilied.

Q&A

1. I wrote logical expression A && B, A < B, A <= B, but my xaml doesn't compile, what's wrong?

As Xaml is generally xml format, some symbols are denied and one should use it's aliases instead os its. See operators aliases table in section Source properties and operators

2. I wrote string expression A + " some text", but my xaml doesn't compile, what's wrong?

In markup extension we can't use double quotes, so we can use single quotes and backslash for escaping \' or xml escape symbol &quot;. See section String, Char and SingleQuotes mode

3. Can I use CalcBinding instead of TemplateBinding?

Yes, you can, but with setting RelativeSource property, see section TemplateBinding

Release notes

version 2.5.2.0

  • Add FallbackValue #37,
  • Disable traces by default, add traces configuration #44. Documentation: Tracing

Thanks to metal450 for waiting 2 years!!

version 2.5.1.0

  • Support .net core 3.0!

PR #57. Thanks to bigworld12 !

version 2.4.0.0

  • Fix performance issues: add parsed expressions cache

bug #56. Thanks to jtorjo!

version 2.3.0.1

  • Add support of implicitly and explicitly castable to boolean types in BoolToVisibilityConverter

(bug #53. Thanks to rstroilov!)

version 2.3.0.0

Possible problems of switching to this version from older versions:

It is important that names of properties, classes and namespaces that make up sources pathes, would be separated from operator ':' in ternary operator (at least one space or parenthesis) for this version. See section Restrictions

version 2.2.5.2

  • fix defect with exception in binding to readonly properties with BindingMode.Default (#41) (thanks to maurosampietro and earthengine!)

Possible problems of switching to this version from older versions:

In older versions CalcBinding creates Binding with BindingMode.TwoWay by default. In new version Binding is created with BindingMode.Default by default (which is more right and standart Binding is doing quite so). Mode = Default means that each DependencyProperty can manage personally in which mode it should be translated. For example, DefaultMode of TextBox.Text is TwoWay, but Label.Content, TextBox.Visibility - OneWay. If you used in you applications TwoWay Binding with DependencyProperty that has DefaultMode = BindingMode.OneWay and you didn't specify Mode=TwoWay in xaml so you need to do it in this version for same work.

example.

<Button Content="TargetButton" Visibility="{c:Binding !HasPrivileges}"/>

In older version it creates BindingMode.TwoWay binding, in new version it creates BindingMode.Default, which translated by Label.Visibility in BindingMode.OneWayMode. If you need to stay on BindingMode.TwoWay then just specify it:

<Button Content="TargetButton" Visibility="{c:Binding !HasPrivileges, Mode=TwoWay}"/>

version 2.2.5.1

  • fix defect with special characters in const strings in path expression (thanks to xmedeko!)

version 2.2.5.0

  • add support of properties that contain digits in there names (thanks to halllo!)

version 2.2.4.0

  • add support of 'null' values: objects that can be null, nullable value types. For nullable value types there are resctrictions, see restrictions page

version 2.2.3.0

  • add 'not' alias for '!' operator

version 2.2.2.0

  • version for .net 4.0

version 2.1.2.0

  • RelativeSource in multibinding support

version 2.1.1.0

  • bug fixes

version 2.1.0.0

  • DataTrigger support
  • bug fixes

version 2.0.0.0

  • support of two way binding, support of automatic invert binding expression and realization inverted binding from dependency property to source
  • Math class support
  • support of nested properties (in nested view-models)
  • bug fixes

version 1.0.0.0

  • binding support
  • supported features: binding/multibinding, algebraic, logic, string and ternary operators
  • support of bool to visibility convertion (two way)

Donation

If you like this project you are welcome to support it!

      USD:

      paypal

 

      RUB:

      paypal

calcbinding's People

Contributors

alex141 avatar bigworld12 avatar halllo avatar wstaelens avatar xmedeko avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

calcbinding's Issues

Possible enhancement

Hi,
I understand this library is called CalBinding and so this may be out of scope but
it would be nice if bindings could parse complex c# expression so it could substitute some trivial converter class. Example:

public class OverlayVisibleConverter : BaseConverter, IMultiValueConverter
{
    public object Convert( object[] values, Type targetType, object parameter, CultureInfo culture )
    {
        bool isKeyboardFocusWithin = (bool)values[ 0 ];
        var passwordBox = (PasswordBox)values[2];

        bool visibile = !isKeyboardFocusWithin && String.IsNullOrEmpty( passwordBox.Password );
        return visibile ? Visibility.Visible : Visibility.Collapsed;
    }  
}


<Label.Visibility>
        <MultiBinding Converter="{StaticResource overlayLabelVisibilityConverter }">
                   <Binding ElementName="passwordBox" Path="IsKeyboardFocusWithin" />
                   <Binding ElementName="passwordBox" Path="SecurePassword" />
                   <Binding ElementName="passwordBox" />
        </MultiBinding>
</Label.Visibility>

Would be nice it it could become something like this, removing the converter class:

  <Label.Visibility>
            <MultiBinding Converter="**{calcBinding:Binding '!passwordBox.IsKeyboardFoucsWithin and passwordBox.SecurePassword'** }">
                  <Binding ElementName="passwordBox" Path="IsKeyboardFocusWithin" />
                  <Binding ElementName="passwordBox" Path="SecurePassword" />
                  <Binding ElementName="passwordBox" />
             </MultiBinding>
 </Label.Visibility>

This probably involve the management of ElementNames.
Do you think it is feasible? I can help out if this is considered helpful.

Thank you.

Is this project still alive?

I really appreciate the effort you put in CalcBinding and i'm aware of the amount of work it is needed to keep a project going.

By the way pull requests are accumulating and new issues are not even being discussed.

If you don't have the time or inclination to support this project anymore, please consider to transfer the project to someone else.

We really need a few fixes :)

Hope to hear you
Thank you

String in parentheses

I have the expression:

<TextBlock Text="{cb:Binding 'IsNew ? \'(new)\' : Name', Mode=OneWay}"  />

But got the error:

System.Windows.Data Warning: 40 : BindingExpression path error: 'new' property not found on 'object' ''UserClientEditViewModel' (HashCode=48653125)'. BindingExpression:Path=nový; DataItem='UserClientEditViewModel' (HashCode=48653125); target element is 'TextBox' (Name=''); target property is 'Text' (type 'String')

When I remove the parentheses \'new\' then it works well.

Can only use equals operator with enum?

I only seem to be able to use the '==' operator for comparing an enum.
Is it possible to use other operators such as '>='?

I tried this:
Visibility="{c:Binding 'CurrentUser.Level>=local:UserLevel.Administrator'}"
And got this error:
Binding error: calc converter can't convert expression{0}>=Enum1.Administrator: The binary operator GreaterThanOrEqual is not defined for the types 'MyNameSpace.UserLevel' and 'MyNameSpace.UserLevel'.

Using the equals operator is working though.

binding enums

hi , i really like the idea of your project , very helpful and time saver
i would like to add the feature of binding to enum values
like an enum with
element1,
element2,
element3

to bind like this
c:Binding path = property Is element1
please tell me if it's possible

In a datagrid, show empty instead of 0

First, i dont want to use decimal? type for every of my field...

So, in my datagridTextColumn, I have the following WORKING statement :

<DataGridTextColumn Header="MyValue" Binding="{conv:Binding '(MyValue==0?-1:MyValue)', StringFormat=C}" />

What it will do, is that when the binded property of the itemSource item is eqal to 0, it replace the 0 per -1. If not 0, then the normal value is shown.

HOWEVER, my real goal here is to show '-' if the value is zero. But I am unable to succeed, because of tons of parsing Error. here are my tries :

<DataGridTextColumn Binding="{conv:Binding '(ProchainCoutant==0?\'-\':ProchainCoutant)'}"/>

ERROR : MarkupExtension is not properly closed

<DataGridTextColumn Binding='{conv:Binding Path="(ProchainCoutant==0?\'-\':ProchainCoutant)"}'/>

ERROR : expected : "

in fact, my problem is that basically, I am just unable to set any quote (\') in my formula

Bug report: Binding Error w Bool-To-Visibility & Template DataType

I've come across what appears to be a bug when using multibindings with bool-to-visibility, where it reports binding errors for templates that shouldn't be applying (based on DataType). Here's code to repro:

<Window x:Class="WpfApplication1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:WpfApplication1"
    xmlns:c="clr-namespace:CalcBinding;assembly=CalcBinding"
    Title="MainWindow" Height="350" Width="525">
<StackPanel>
    
    <ContentControl x:Name="contentControl" Content="{Binding}">
        <ContentControl.Resources>
            
            <DataTemplate DataType="{x:Type local:ClassSimple}">
                <TextBlock>I am ClassSimple</TextBlock>
            </DataTemplate>

            <DataTemplate DataType="{x:Type local:ClassComplex}">
                <GroupBox>
                    <TextBlock>I am ClassComplex: <TextBlock Visibility="{c:Binding 'SomeProperty || SomeProperty2'}" /></TextBlock>
                </GroupBox>
            </DataTemplate>
            
        </ContentControl.Resources>
    </ContentControl>

    <Button Content="ClassSimple" Click="Click_ClassSimple"/>
    <Button Content="ClassComplex" Click="Click_ClassComplex"/>
</StackPanel>    
</Window>

And in CodeBehind:

public class ClassSimple { }
public class ClassComplex { public bool SomeProperty { get; set; } public bool SomeProperty2 { get; set; } }

private void Click_ClassSimple(object sender, RoutedEventArgs e)
{
    contentControl.DataContext = new ClassSimple();
}

private void Click_ClassComplex(object sender, RoutedEventArgs e)
{
    contentControl.DataContext = new ClassComplex();
}

If you click "ClassSimple," all is as expected. But if you click "ClassComplex" then "ClassSimple," you'll get:

Binding error: one of source fields is Unset, return null
System.Windows.Data Error: 5 : Value produced by BindingExpression is not valid for target property.; Value='<null>' MultiBindingExpression:target element is 'TextBlock' (Name=''); target property is 'Visibility' (type 'Visibility')

Oddly, if you remove the GroupBox in the ClassComplex template, the binding error goes away. Likewise, it goes away if you just bind to SomeProperty or SomeProperty2 (not both).

Null-conditional operator support and null

To calculate the visibilty of a control i'm using CalcBinding something like 'A?.B?.C > 0'.

I get a binding error saying "Value produced by BindingExpression is not valid for target property.; Value=''"

I also tried 'A != null and A.B != null and A.B.C > 0' but i can't get it to work.

So the question: is Null-conditional operator supported?
Is it null supported in comparisons?

Thanks

P.S. - A naive converter works just fine

public class CarouselVisibility : BaseConverter, IValueConverter
{
   public object Convert( object value, Type targetType, object parameter, CultureInfo culture )
   {
       var vm = value as ViewModel;
       return vm?.A?.B?.C?.Count > 0 ? Visibility.Visible : Visibility.Collapsed;
   }
   public object ConvertBack( object value, Type targetType, object parameter, CultureInfo culture )
   {
      throw new NotImplementedException();
   }
}

Binding x:Static NRE

I have working Binging

<TextBlock Visibility="{Binding Source={x:Static myProp:Settings.BoolSetting}, Converter={StaticResource BooleanToVisibilityConverter}}" />

However, the CalcBinding fail

<TextBlock Visibility="{cb:Binding Source={x:Static myProp:Settings.BoolSetting}" />

with

System.NullReferenceException: Object reference not set to an instance of an object.
   at CalcBinding.Binding.NormalizePath(String path)
   at CalcBinding.Binding.ProvideValue(IServiceProvider serviceProvider)

FallbackValue

I'm direly missing support for FallbackValue (from BindingBase), which should be used when the expression can't be compiled/evaluated/throws. Is it feasible to add?

porting to uwp?

Hi @Alex141 ,

First off, I insanely LOVE your library! I have used it for several years!
Soon (within 1 month or so), I will have to port my app to UWP. I am a beginner at UWP.

Since both WPF and UWP use binding, I would assume porting it would be easy. But since there's a request for this for 1.5 years (CommunityToolkit/WindowsCommunityToolkit#1790), I'm asssuming it's waay more complicated than I think.

I will have to, one way or another, port this to uwp. Any pointers as to what complications I should expect?

Background:
I insanely hate UWP, but for the upcoming months (until WinUI gets to version 3.0), I don't have a choice. Long story short, I want to use win2d, and using Xaml Islands is just a sad joke.

Best,
John

Support for MultiValue converter

I would like to use my custom converter inside the CalcBinding. A reason is that WPF Binding automatically listen to the PropertyChanged events, so I do not need to create a view model with the event subscribe and unsubscribe.

My idea is something like

<MultiBinding Converter="{cb:MultiBinding P0 and P1}" >
    <Binding Path="IsSomething"/>
    <Binding Path="MyEnumProperty" Converter="{StaticResource MyEnumToBoolConverter}"/>
</MultiBinding>

Or maybe P[0] and P[1] instead of P0 and P1.

How to use Static properties

Here is what I have:

<Window x:Class="MySuperApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:MySuperApp"
        mc:Ignorable="d"
        xmlns:sys="clr-namespace:System;assembly=mscorlib"
        d:DataContext="{d:DesignInstance {x:Type dvm:DesignMainWindowViewModel}, IsDesignTimeCreatable=True}"
        xmlns:c="clr-namespace:CalcBinding;assembly=CalcBinding"
        Title="{Binding Title}"
        x:Name="this_" d:DesignWidth="1600" d:DesignHeight="900">

    <Window.Resources>

        <sys:Double x:Key="IconHeigh">55</sys:Double>
        <sys:Double x:Key="IconWidth">55</sys:Double>
...
    </Window.Resources>

and then :
<Path Stretch="Uniform" Fill="Black" Height="{c:Binding 'local:IconHeigh - 10'}" Data="M15,... ,2,0z" />
The binding expression is wrong - I can't figure out what it should be. Can you help please?

Error in WPF-Xaml Editor, binding is working though

Hi,
the following Tooltip-Binding is throwing an xaml-error in visual-studio:

ToolTip="{c:Binding '(myValue>0 ? \'sentence one\' : \'sentence two\')'}"

"markup extension is not properly closed".

It's working fine in the app at runtime though.

How do i fix that?
Thanks!

Does not work with read-only propeties

I have a read-only property

public bool IsEmpty  { get { ... } };

<TextBlock Visibility="{cb:Binding IsEmpty}" />

But the CalcBinding fails with TwoWay or OneWayToSource binding cannot work on the read-only property 'IsEmpty'.

When I add set to my property (doing nothing), then it works OK.

DataTemplate bind to the whole item

I have a <ListBox> with <DataTemplate> and I need to bind Visibility to the condition, if the item is null or not. In a bare WPF I use

<TextBlock Text="Item is null" Visibility="{Binding Converter={StaticResource IsNullConverter}}" />

However, I would like to use a fancy CalcBinding, something like

<TextBlock Text="Item is null" Visibility="{cb:Binding '. == null'" />

How to denote the whole item in the expression (. is not working).

slow startup

Hi Alex,

First off, insanely awesome lib! Been using it for more than a year now!
Having said that, when there's a LOT of databinding initializations, the startup is really slow.
I basically have a list of databound controls. For 240 controls, it takes roughly 10-12 seconds to startup.

Imagine this code:

foreach (var beat in model.music_beats) {
    var ctrl = new music_beat_ctrl { DataContext = beat, Height = ActualHeight};
    canvas.Children.Add(ctrl);
}

Each music_beat_ctrl is databound, more or less:

<materialDesign:PackIcon Kind="Link" RenderTransformOrigin="0.5,0.5" Width="18" Height="18" Margin="-9 0 0 0"
Visibility="{c:Binding 'linked or highlighted'}"
Foreground="{c:Binding 'highlighted ? media:Brushes.LightSeaGreen : media:Brushes.DimGray'}"
/>

<materialDesign:PackIcon Kind="GuitarElectric" Foreground="DimGray"
Width="{c:Binding 'type == local:beat_type.major ? 18 : 12'}"
Height="{c:Binding 'type == local:beat_type.major ? 18 : 12'}"
Opacity="{c:Binding 'type == local:beat_type.major ? 1 : 0.3'}"
ToolTip="{c:Binding 'type == local:beat_type.major ? 'Major Beat' : 'Minor Beat''}"
/>

While doing profiling, it seems to end up calling DynamicExpresso.Interpretor.constructor 960 times, which ends up with 28800 calls to DynamicExpresso.Interpretor.Reference - I would assume these should be able to be cached somehow?

Custom types with defined implicit cast to bool are unsupported by BoolToVisibility converter

I faced in issue in my project. When using a type which has defined implicit cast to bool in a property, binding visibility to that property doesn't work and conversion fails with following message:
System.InvalidCastException: Specified cast is not valid.

It happens because of explicit cast is called on value in BoolToVisibilityConverter.Convert:
if ((bool)value) return Visibility.Visible;

this test reproduces issue:

        [Test]
        public void DoesNotFailConvertingWhenValueHasImplicitConversionToBool()
        {
            Assert.DoesNotThrow(() =>
                new BoolToVisibilityConverter()
                .Convert(new CastableToBoolean(true), typeof(Visibility), null, CultureInfo.CurrentCulture));
        }

        private sealed class CastableToBoolean
        {
            private bool value;

            public CastableToBoolean(bool value = false)
            {
                this.value = value;
            }

            public static implicit operator bool(CastableToBoolean obj)
            {
                return obj.value;
            }
        }

How to compose expression to compare property with enum value?

I didn't find a way how to bind visibility with enum compare condition:
<WrapPanel Margin="5" Visibility="{c:Binding 'MyProperty==Value1'}">
Instead of Value1 I tried also MyEnumType.Value1, local:MyEnumType.Value1, nothing helps, everything result is 'Visible' with error:
System.Windows.Data Warning: 40 : BindingExpression path error: 'Value1' property not found on 'object' ''TabModel' (HashCode=42904806)'. BindingExpression:Path=local; DataItem='TabModel' (HashCode=42904806); target element is 'WrapPanel' (Name=''); target property is 'Visibility' (type 'Visibility')

Different types multibing

Is it possible to use multibinding for different types of arguments?:

Content="{c:Binding Path='\'Points: \' + Points'}" 

where Points is int property.
It returns me error like:
Binding error: calc converter can't convert expression"Points"+{0}: Expression of type 'System.Int32' cannot be used for parameter of type 'System.Object' of method 'System.String Concat(System.Object, System.Object)'

WPF binding engine only takes the StringFormat property into account when the target property is of the String type. For properties of the Object type (like the BarStaticItem.Content property), the StringFormat property is ignored.
For instance this behavior in the standard Label control:

<Label Content="{Binding SomeProperty, StringFormat=This string will not be displayed}" />

Why I am looking may be there is some solution with your library.
Thanks.

Support for nullable types

I have a bool? property and bind it to Visibility:

Visibility="{cb:Binding 'IsConnected == null || IsConnected == false'}"

I got error Binding error: one of source fields is Unset, return null. Is it possible to work with nullable types?

Add a version for UWP

Hi, It's a very useful library. Please add a version that supports Universal Windows Apps.
Thanks.

Doesn't work for Setters

Error is returned:
'Binding' is not valid for Setter.Value. The only supported MarkupExtension types are DynamicResourceExtension and BindingBase or derived types

Mode exception if getter only properties

I get an exception every time i forget to set Mode=OneWay for getter-only properties.
is it possible to autodetect such properties and automatically set binding Mode=OneWay?

Enum inside classes

Seems like they are not supported yet, just outside classe directly in the namespace

Resharper compatibility

Such 'complex' property access shown as error in Resharper:
<Setter Property="IsEnabled" Value="{c:Binding !DataContext.IsRemoved}"/>
! pointed as not expected token.
And I can not ignore this line something like
<!-- ReSharper disable Xaml.BindingWithContextNotResolved -->
Only was is Disable Resharper Daemon for all file, but i don't like it much.

Is there some workaround?

I can not use string methods (StartsWith)... Or can I?

Hi,
I can not use string methods, because I can not convert input object to string....
Non of the trials below does not work:

  • using "System.": System.String(TxtVersion)).StartsWith('0')
  • using "System:": System:String(TxtVersion)).StartsWith('0')

or can I use (in a different way)?

Support of custom converters

Create ability to set user custom Converters to c:Binding.

For Binding: if converter is defined then call it after source -> target binding and before target -> source binding
For MultiBinding: if converter is defined then call it after source -> target binding. (for multibinding we have one mode permanently)

How to escape the equals sign?

In XAML the equals sign is an special character on attribute values.

How to write the following expression?

Visibility ="{c:Binding Value == null}"

Thanks

bug in dynamic expresso with parameters order

There is a bug in library dynamic expresso. Order of params, that transfer to Invoke() method should be the same as order of parameters, transfered to Interpreter.Parse() method, but is the same as the order in which the parameters are occured in the expression.
See example:

        var Parameter1 = new Parameter("a", typeof(int));
        var Parameter2 = new Parameter("b", typeof(int));

        var expr = new Interpreter().Parse("b-a", Parameter1, Parameter2);

        Console.WriteLine(expr.Invoke(1, 2));
        Console.ReadLine();

Expected: 1 (as a = 1, b = 2)
Real: -1 (b = 1, a = 2)

Because of this bug MathConverter can accept only such templates: {0}..{1}..{2} etc

porting to UWP - a nogo for me

Hi Alex,

Once again, I insanely love your lib! I wanted to start working on porting this to UWP, but I hit quite a few blockers.

For once, the idiots at UWP, don't have a "Visibility.Hidden" enum. Then, there's no Binding.Default. Those are the minor issues.

The big issues are : there's no IMultiValueConverter, and MarkupExtension is not implemented the same:
You're expecting
public override object ProvideValue(IServiceProvider serviceProvider)
but you get
public override object ProvideValue()

I didn't manage to figure out how to get a serviceProvider, and wasn't exactly sure what it was for, and long story short, there way too many issues.

I still hate UWP with all my heart, but unfortunately I need it , because of win2d.

So, I came up with a workaround, which is decent for me:

    public bool is_sel_hov => expression_value(is_selected || is_hovering, "is_selected || is_hovering", PropertyChanged);
    public string full_name => expression_value(user_name + " " + password, "user_name password", PropertyChanged);

Both is_sel_hov and full_name automatically trigger notification updates when is_selected/is_hoverint/user_name/password change.

It's not ideal, but for now it's enough for me.

Best,
John

Use for TemplateBinding

I would like to use CalcBinding for TemplateBinding in Style definitrion, too. If it is already possible, add example to the README.md, thanks.
(Maybe using some kind of {TemplateBinding Separator, Converter=cb:CalcConverter ...}?)

Ternary expression with color

As the same as

<TextBlock Text="{c:Binding '(1 == 2) ? 10 : 20'}" />

We may expect that

<TextBlock Text="Test" Foreground="{c:Binding '(1 == 1) ? #ff0000 : #000000'}" VerticalAlignment="Center"/>

display text in red.
Unfortanutelly, no text is displayed

Thank you :)

Binding does not get updated after property changes

If i bind to MySubView.MyOtherProperty the expression is not reevaluated with the correct value of the property when its value changes.

CalcConverter.Convert is not even called. The binding just does not work.
I don't really have time to study the problem and submit a solution so please help me out.

Thank you.

Support for Canvas.Left, etc (attached properties)

A very important use case is to calculate based on the position of a component in a canvas. I don't see any support for this. Do you know the status of this?

I need to use (Canvas.Left) + Width + (some constant integer) and (Canvas.Top) + Height + (some constant integer) in my calculation.

Bug with Or and And parse

Or is replaced to || even if or is a part of long named property, e.g. Coordinates. with "and" there is analog situation.

Automated Test Cases

I think this library would do well with having automated test cases. The parser seems to not be perfect right now, (see #33). If I change something, I want to be sure I'm not breaking other functionality.

Add NotNullToVisibility

Add NotNullToVisibility behaviour so we can write just

<Button Visibility="{calc:Binding SelectedItem, Mode=OneWay}" />

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.