CPF 入门教程 - 数据绑定和命令绑定(二)
CPF netcore跨平台UI框架
系列教程
CPF 入门教程 - 数据绑定和命令绑定(二)
数据绑定和Wpf类似,支持双向绑定。数据绑定和命令绑定是UI和业务逻辑分离的基础。
首先,你需要定义个MainModel,为了可以有属性通知,这个类可以继承CpfObject或者自己实现INotifyPropertyChanged
public class MainModel : CpfObject
{
[PropertyMetadata("默认值")]
public string Test
{
get { return (string)GetValue(); }
set { SetValue(value); }
}
}
这里定义了一个Test属性,并且设置默认值为“默认值”
设计个测试界面,加个TextBlock和Button,同时TextBlock设置绑定,绑定定义在Bindings属性, {nameof(TextBlock.Text),nameof(MainModel.Test) } 表示TextBlock的Text绑定到DataContext的Test属性
public class Window4 : Window
{
protected override void InitializeComponent()
{
Title = "标题";
Width = 344.8f;
Height = 126.4f;
Background = null;
Children.Add(new WindowFrame(this, new Panel
{
Width = "100%",
Height = "100%",
Children =
{
//内容元素放这里
new Button
{
MarginLeft = 223.8f,
MarginTop = 25.7f,
Height = 28f,
Width = 67.4f,
Content = "Button",
},
new TextBlock
{
MarginLeft = 36.7f,
MarginTop = 31.6f,
Text = "TextBlock",
Bindings =
{
{nameof(TextBlock.Text),nameof(MainModel.Test) }
}
},
}
}));
LoadStyleFile("res://ConsoleApp1.Stylesheet1.css");
//加载样式文件,文件需要设置为内嵌资源 }
}

修改program,设置Window的DataContext和CommandContext
var model = new MainModel();
Application.Run(new Window4 { DataContext = model, CommandContext = model });
写好之后,运行看看效果。TextBlock那边显示MainModel那边定义的默认值

接下来定义命令,通过按钮点击修改Test值,同时自动更新到TextBlock
MainModel里增加个Click方法
class MainModel : CpfObject
{
[PropertyMetadata("默认值")]
public string Test
{
get
{
return (string)GetValue();
}
set
{
SetValue(value);
}
} public void Click()
{
Test += "test";
}
}
Button那边增加命令绑定,Commands里添加, {nameof(Button.Click),nameof(MainModel.Click) } 表示Button的Click事件绑定到CommandContext的Click方法
new Button
{
MarginLeft = 223.8f,
MarginTop = 25.7f,
Height = 28f,
Width = 67.4f,
Content = "Button",
Commands =
{
{nameof(Button.Click),nameof(MainModel.Click) }
}
},
运行效果,点击一次增加一次test。这就是最简单的模型视图分离的数据绑定

接下来绑定集合
设计界面,添加Button和ListBox

往MainModel里加上Items集合属性,构造函数里初始化集合,用 Collection 是为了有集合变化通知,也可以使用 ObservableCollection。 (string, string) 就是元组里简化的结构体类型定义,是一种偷懒简化数据定义的方式,不过这种方式的话,改item就不能更新到UI了,需要可以更新到UI的就需要自定义类型,继承CpfObject或者继承INotifyPropertyChanged的类型作为Item
public MainModel()
{
Items = new Collection<(string, string)>();
} public Collection<(string,string)> Items
{
get
{
return (Collection<(string, string)>)GetValue();
}
set
{
SetValue(value);
}
}
MainModel里加个AddItem方法
public void AddItem()
{
Items.Add(("test" + Items.Count, Items.Count.ToString()));
}
最终代码
using CPF;
using System;
using System.Collections.Generic;
using System.Text; namespace ConsoleApp1
{
class MainModel : CpfObject
{
[PropertyMetadata("默认值")]
public string Test
{
get
{
return (string)GetValue();
}
set
{
SetValue(value);
}
} public void Click()
{
Test += "test";
} public MainModel()
{
Items = new Collection<(string, string)>();
} public Collection<(string, string)> Items
{
get
{
return (Collection<(string, string)>)GetValue();
}
set
{
SetValue(value);
}
} public void AddItem()
{
Items.Add(("test" + Items.Count, Items.Count.ToString()));
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CPF;
using CPF.Drawing;
using CPF.Controls;
using CPF.Shapes;
using CPF.Styling;
using CPF.Animation; namespace ConsoleApp1
{
public class Window4 : Window
{
protected override void InitializeComponent()
{
Title = "标题";
Width = 338.4f;
Height = 205.6f;
Background = null;
Children.Add(new WindowFrame(this, new Panel
{
Width = "100%",
Height = "100%",
Children =
{
//内容元素放这里
new Button
{
MarginLeft = 223.8f,
MarginTop = 25.7f,
Height = 28f,
Width = 67.4f,
Content = "Button",
Commands =
{
{
nameof(Button.Click),
nameof(MainModel.Click)
}
}
},
new TextBlock
{
MarginLeft = 36.7f,
MarginTop = 31.6f,
Text = "TextBlock",
Bindings =
{
{
nameof(TextBlock.Text),
nameof(MainModel.Test)
}
}
},
new Button
{
MarginLeft = 223.8f,
MarginTop = 91.6f,
Height = 28f,
Width = 67.4f,
Content = "添加Item",
Commands =
{
{nameof(Button.Click),nameof(MainModel.AddItem) }
}
},
new ListBox
{
SelectedValuePath = "Item2",//绑定Item里的Item1属性
DisplayMemberPath = "Item1",//绑定Item里的Item2属性
BorderStroke = "1,Solid",
BorderFill = "#DEDEDE",
MarginLeft = 36.7f,
MarginTop = 60.8f,
Height = 76.5f,
Width = 123.2f,
Bindings =
{
{nameof(ListBox.Items),nameof(MainModel.Items) }
}
},
}
}));
LoadStyleFile("res://ConsoleApp1.Stylesheet1.css");
//加载样式文件,文件需要设置为内嵌资源
}
}
}
最终运行效果,点击添加Item的按钮,ListBox里会增加Item

数据类型转换,Test属性值后面加1。 数据转换器用方法或者Lambda就行。
{
nameof(TextBlock.Text),
nameof(MainModel.Test),
null,
BindingMode.OneWay,
(string a)=>a+""
}

UI元素之间绑定,TextBox的Text绑定到Button的Content,其中TextBox设置PresenterFor=this,是为了标记TextBox的作用域在当前类,因为Name是可以重复的,元素嵌套如果有相同Name会无法判断元素是在哪里的,所以用PresenterFor加标记判断,而且这样可以通过FindPresenterByName方法来获取当前类里的标记元素来绑定
protected override void InitializeComponent()
{
Title = "标题";
Width = 338.4f;
Height = 205.6f;
Background = null;
Children.Add(new WindowFrame(this, new Panel
{
Width = "100%",
Height = "100%",
Children =
{
//内容元素放这里
new Button
{
MarginLeft = 223.8f,
MarginTop = 25.7f,
Height = 28f,
Width = 67.4f,
Content = "Button",
Commands =
{
{
nameof(Button.Click),
nameof(MainModel.Click)
}
},
Bindings =
{
{
nameof(Button.Content),
nameof(TextBox.Text),
FindPresenterByName("textBox")
}
}
},
new TextBlock
{
MarginLeft = 36.7f,
MarginTop = 31.6f,
Text = "TextBlock",
Bindings =
{
{
nameof(TextBlock.Text),
nameof(MainModel.Test),
null,
BindingMode.OneWay,
(string a)=>a+""
}
}
},
new Button
{
MarginLeft = 223.8f,
MarginTop = 91.6f,
Height = 28f,
Width = 67.4f,
Content = "添加Item",
Commands =
{
{
nameof(Button.Click),
nameof(MainModel.AddItem)
}
}
},
new ListBox
{
SelectedValuePath = "Item2",
//绑定Item里的Item1属性
DisplayMemberPath = "Item1",
//绑定Item里的Item2属性
BorderStroke = "1,Solid",
BorderFill = "#DEDEDE",
MarginLeft = 36.7f,
MarginTop = 60.8f,
Height = 76.5f,
Width = 123.2f,
Bindings =
{
{
nameof(ListBox.Items),
nameof(MainModel.Items)
}
}
},
new TextBox
{
Name="textBox",
PresenterFor=this,
AcceptsReturn= false,
HScrollBarVisibility= ScrollBarVisibility.Hidden,
VScrollBarVisibility= ScrollBarVisibility.Hidden,
MarginLeft = 144.8f,
MarginTop = 28.1f,
Width = 74.5f
},
}
}));
LoadStyleFile("res://ConsoleApp1.Stylesheet1.css");
//加载样式文件,文件需要设置为内嵌资源
}
TextBox输入,会自动更新Button的文字

命令绑定除了事件之外,属性变化也可以绑定为命令,比如,鼠标移入和移出就调用
Commands =
{
{
nameof(Button.IsMouseOver),
nameof(MainModel.Click)
}
}
主要绑定就这些,如果要双向绑定,命令参数等等,看VS那边的智能提示
CPF 入门教程 - 数据绑定和命令绑定(二)的更多相关文章
- CPF 入门教程 - 样式和动画(三)
CPF NetCore跨平台UI框架 系列教程 CPF 入门教程(一) CPF 入门教程 - 数据绑定和命令绑定(二) CPF 入门教程 - 样式和动画(三) 用样式可以对内部元素进行批量设置属性. ...
- CPF 入门教程 - 绘图(四)
CPF NetCore跨平台UI框架,增加了Vlc支持跨平台播放视频. 系列教程 CPF 入门教程(一) CPF 入门教程 - 数据绑定和命令绑定(二) CPF 入门教程 - 样式和动画(三) CPF ...
- CPF 入门教程 - 控件布局(六)
CPF netcore跨平台桌面UI框架 系列教程 CPF 入门教程(一) CPF 入门教程 - 数据绑定和命令绑定(二) CPF 入门教程 - 样式和动画(三) CPF 入门教程 - 绘图(四) C ...
- CPF 入门教程 - 设计器和模板库的使用(五)
CPF netcore跨平台UI框架 系列教程 CPF 入门教程(一) CPF 入门教程 - 数据绑定和命令绑定(二) CPF 入门教程 - 样式和动画(三) CPF 入门教程 - 绘图(四) CPF ...
- CPF 入门教程 - 属性和事件(七)
CPF C#跨平台桌面UI框架 系列教程 CPF 入门教程(一) CPF 入门教程 - 数据绑定和命令绑定(二) CPF 入门教程 - 样式和动画(三) CPF 入门教程 - 绘图(四) CPF 入门 ...
- CPF 入门教程 - 各个控件介绍(八)
CPF C#跨平台桌面UI框架 系列教程 CPF 入门教程(一) CPF 入门教程 - 数据绑定和命令绑定(二) CPF 入门教程 - 样式和动画(三) CPF 入门教程 - 绘图(四) CPF 入门 ...
- CPF 入门教程 - 各平台各系统发布说明(九)
CPF C#跨平台桌面UI框架,支持Windows,Mac,Linux,支持龙芯.飞腾等CPU 系列教程 CPF 入门教程(一) CPF 入门教程 - 数据绑定和命令绑定(二) CPF 入门教程 - ...
- WPF中的命令与命令绑定(二)
原文:WPF中的命令与命令绑定(二) WPF中的命令与命令绑定(二) 周银辉在WPF中,命令(Commandi ...
- Elasticsearch入门教程(六):Elasticsearch查询(二)
原文:Elasticsearch入门教程(六):Elasticsearch查询(二) 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:h ...
随机推荐
- reCAPTCHA无法加载?一个小工具就可以轻松解决!
Chrome用户可以在应用商店搜索gooreplacer安装,或者点我下载,然后打开chrome://extensions/,将下载的crx文件拖入浏览器窗口,即可完成安装 Firefox用户可以在 ...
- super,this关键字用法 Java
super 用法 1.调用父类变量2.调用父类方法3.子类构造方法第一句 this 用法 super关键字用来访问父类内容, this 关键字用来访问本类中的内容, 有三种用法 1.在本类的成员方法中 ...
- 题解 洛谷 P6142 【[USACO20FEB]Delegation P】
和赛道修建类似,先对\(k\)进行二分,将最值问题转化为判定问题. 在判定一个\(k\)是否合法时,贪心去考虑,一个节点下面的若干条链在合并时,一条链肯定和另一条使它合并后恰好满足长度限制的链合并最优 ...
- freeRTOS内核学习笔记(1)-编程标准
在开始具体的学习之前,你应该先了解freeRTOS的编程标准.这能够方便你在接下来的阅读中快速的了解一些内容 的基本信息,并方便记忆.此外,良好的编程风格也是工作效率的保障. 你可以在https:// ...
- 痞子衡嵌入式:恩智浦i.MX RTxxx系列MCU特性那些事(1)- 概览
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是恩智浦i.MX RTxxx系列MCU的基本特性. 恩智浦半导体于2017年开始推出的i.MX RT系列重新定义了MCU,其第一款芯片i. ...
- PHP 表单和用户输入讲解
PHP 表单和用户输入 PHP 中的 $_GET 和 $_POST 变量用于检索表单中的信息,比如用户输入. PHP 表单处理 有一点很重要的事情值得注意,当处理 HTML 表单时,PHP 能把来自 ...
- electron-react-umi模板
electron-react-umi-tpl github English Version 更新日志: 2020-06-08 添加全量更新功能 2020-06-29 添加远程增量更新功能,无需下载包来 ...
- js 读取word和txt(react版) + 正则分割段落
show the code 前提:需要mammoth包~ import React, { useState, useReducer } from 'react'; import { Button, A ...
- java开发-flyway
数据库版本管理工具 什么是数据库版本管理? 做过开发的小伙伴们都知道,实现一个需求时,一般情况下都需要设计到数据库表结构的修改.那么我们怎么能保证项目多人开发时,多个数据库环境(测试,生产环境)能够保 ...
- Docker 基础知识 - 使用 tmpfs 挂载(tmpfs mounts)管理应用程序数据
卷(volumes) 和 绑定挂载(bind mounts) 允许您在主机和容器之间共享文件,这样即使在容器停止后也可以持久存储数据. 如果在 Linux 上运行 Docker,那么还有第三种选择:t ...