title author date CreateTime categories
WPF 在绑定表达式添加计算
lindexi
2018-12-22 16:12:56 +0800
2018-12-22 15:43:54 +0800
WPF

很多时候一些简单的使用绑定需要对绑定的源做处理就需要通过转换器,这样的代码写起来不好看
本文告诉大家通过一个简单的库可以实现在界面绑定的时候通过表达式不需要转换

首先通过 Nuget 安装 CalcBinding 库,注意 Nuget 的地址是 https://api.nuget.org/v3/index.json 如果没有找到这个库就请复制链接点击更新,再输入 CalcBinding 寻找

在使用这个库之前需要引用命名空间,打开 MainWindow.xaml 文件,添加命名空间

xmlns:c="clr-namespace:CalcBinding;assembly=CalcBinding"

然后创建一个数据用来绑定

    public class ViewModel : INotifyPropertyChanged
{
public double A
{
get => _a;
set
{
if (value.Equals(_a)) return;
_a = value;
OnPropertyChanged();
}
} public double B
{
get => _b;
set
{
if (value.Equals(_b)) return;
_b = value;
OnPropertyChanged();
}
} public double C
{
get => _c;
set
{
if (value.Equals(_c)) return;
_c = value;
OnPropertyChanged();
}
} public event PropertyChangedEventHandler PropertyChanged;
private double _a = 1;
private double _b = 2;
private double _c; [NotifyPropertyChangedInvocator]
private void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}

这时在界面如果需要创建一个 TextBlock 绑定三个值 A + B + C 就可以通过下面的方法

        <TextBlock Text="{c:Binding A+B+C}" HorizontalAlignment="Center" VerticalAlignment="Center"></TextBlock>

通过直接写表达式的方式就可以,十分简单

那如果需要加上一些常量怎么做,如计算 0.5*A+B 可以怎么写?

<TextBlock Text="{c:Binding 0.5*A+B}" />

修改一下界面然后运行

            <StackPanel>
<TextBlock>
<Run Text="A=" />
<Run Text="{Binding A}" />
</TextBlock>
<TextBlock>
<Run Text="B=" />
<Run Text="{Binding B}" />
</TextBlock>
<TextBlock>
<Run Text="C=" />
<Run Text="{Binding C}" />
</TextBlock>
<TextBlock Text="0.5*A+B" />
<TextBlock Text="{c:Binding 0.5*A+B}" />
</StackPanel>

如果此时的还有一些布尔量怎么办?打开 ViewModel 类添加下面代码

        public bool BoolA
{
get => _boolA;
set
{
if (value == _boolA) return;
_boolA = value;
OnPropertyChanged();
}
} public bool BoolB
{
get => _boolB;
set
{
if (value == _boolB) return;
_boolB = value;
OnPropertyChanged();
}
} private bool _boolB;
private bool _boolA = true;

如果需要绑定 A 和 B 可以这样写

<TextBlock Text="{c:Binding BoolA and BoolB}" />
<TextBlock Text="{c:Binding BoolA or BoolB}" />
<TextBlock Text="{c:Binding BoolA and BoolB or BoolB}" />

修改一下界面

            <StackPanel>
<TextBlock>
<Run Text="A=" />
<Run Text="{Binding BoolA}" />
</TextBlock>
<TextBlock>
<Run Text="B=" />
<Run Text="{Binding BoolB}" />
</TextBlock>
<TextBlock Text="A and B" />
<TextBlock Text="{c:Binding BoolA and BoolB}" />
<TextBlock Text="A or B" />
<TextBlock Text="{c:Binding BoolA or BoolB}" />
</StackPanel>

其他可以写的是表达式

<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}

判断布尔

<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)}"/>

因为在 xaml 不能使用 && || <= 所以需要使用 and or 'less=' 替换

另外对于 : 之前需要添加空格,如下面代码

<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 -->

这些都是对的,但是下面的代码是无法运行

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

可以绑定静态的值,静态的值的写法 xmlNamespace:Class.StaticProperty.NestedProperty 命名空间下的类的静态属性的属性

对于经常计算值这里也可以简单使用,如 Math 里面的方法

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

枚举值也可以点命名空间的枚举的值,可以用来判断 xmlNamespace:EnumClass.Value 如在 Foo 枚举里面有 A 这个值

<CheckBox IsChecked="{c:Binding 'Foo==local:Foo.A'}" />

经常会将 bool 转换为 Visibility 这个库也有简单的方法

<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}"/>

如果需要在样式使用,需要通过 RelativeSource 找到方法

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

Alex141/CalcBinding: Advanced WPF Binding which supports expressions in Path property and other features

最新文章

  1. Mac下搭建php开发环境【转】
  2. JavaScrip的DOM操作(13号讲)
  3. 第一百九十三天 how can I 坚持
  4. 采用thinkphp框架实现添加管理员功能
  5. Java JPA 查询实体部分字段
  6. StretchDIBits使用方法
  7. Python之路day4
  8. javascript笔记整理(运算符 )
  9. HTML5 Web SQL Database 与 Indexed Database 的 CRUD 操作
  10. html标签中head中两个标签的作用
  11. JSP中使用Taglib
  12. Linux下安装ActiveMQ CPP
  13. 浅谈linux虚拟内存结构
  14. hive 中遇到的正则
  15. 洛谷P3321 序列统计
  16. 2017-12-15python全栈9期第二天第三节之使用while循环输出0到10不包含7
  17. 信用评分卡 (part 7 of 7)
  18. Service Mesh
  19. PTA 复数四则运算
  20. mongodb操作符

热门文章

  1. 1.2 JSX 语法
  2. MyBatis-Spring(二)--SqlSessionTemplate实现增删改查
  3. docker常用
  4. null == null 或者 [] == [] 或者{} == {} 或者alert(1|| 2) 或者alert(1&amp;&amp; 2) 结果及原理
  5. 搭建WordPress博客程序库
  6. uname - 显示输出系统信息
  7. 读书笔记---《Docker 技术入门与实践》---其一
  8. Algo: Binary search
  9. node 模板引擎使用的步奏
  10. Ruby 命令行选项