WPF 用户控件的自定义依赖属性在 MVVM 模式下的使用备忘
依赖属性相当于扩充了 WPF 标签的原有属性列表,并可以使用 WPF 的绑定功能,可谓是十分方便的;用户控件则相当于代码重用的一种方式;以上几点分开来还是比较好理解的,不过要用到MVVM 模式中,还是要探索一番的。
我们先新建一个用户控件(UC_FoodsPanel.xaml),里面放一个 StackPanel:
XHTML
- <UserControl x:Class="Note.UC_FoodsPanel"
- xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
- xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
- xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
- mc:Ignorable="d"
- d:DesignHeight="450" d:DesignWidth="800">
- <StackPanel x:Name="SpFoods" MinWidth="620"/>
- </UserControl>
然后在其后台添加依赖属性相关代码:
C#
- public List<UC_FoodItem> Items
- {
- get => (List<UC_FoodItem>)GetValue(ItemsProperty);
- set => SetValue(ItemsProperty, value);
- }
- // Using a DependencyProperty as the backing store for Items. This enables animation, styling, binding, etc...
- public static readonly DependencyProperty ItemsProperty =
- DependencyProperty.Register(nameof(Items), typeof(List<UC_FoodItem>), typeof(UC_FoodsPanel),
- new PropertyMetadata(null, PropertyChangedCallback, null));
- private static void PropertyChangedCallback(DependencyObject obj, DependencyPropertyChangedEventArgs args)
- {
- if (args.NewValue is List<UC_FoodItem> newValue)
- {
- try
- {
- var control = obj as UC_FoodsPanel;
- control.SpFoods.Children.Clear();
- foreach (var item in newValue)
- {
- control.SpFoods.Children.Add(item);
- }
- }
- catch (Exception ex)
- {
- Console.WriteLine(ex.ToString());
- MessageBox.Show($"载入数据出错:{ex.Message}");
- }
- }
- }
依赖属性相关内容可参考网上的《WPF 系列 —— 控件添加依赖属性 – 朝兮兮 – 博客园》 一文,添加依赖属性的方法为 —— 输入 propdp 再双击 tab 键。
上面代码中,我们添加的依赖属性为 Items,是一个 UC_FoodItem 类的列表。关键在于属性改变时的回调函数 PropertyChangedCallback,其 obj 参数代表属性绑定的控件,即此处的 UC_FoodsPanel,args 参数中有 OldValue 和 NewValue,分别代表属性改变前后的值。此处即取改变后的值 —— 一个列表 —— 赋给用户控件中的 StackPanel。
这样之后,我们在其它页面(Views\\MainWindowView.xaml)使用这个用户控件的时候,就可以使用 Items 属性了:
XHTML
- <note:UC_FoodsPanel Items="{Binding Items}"></note:UC_FoodsPanel>
然后在这个页面的 ViewModel 中(ViewModels\\MainWindowViewModel.cs)设置需要绑定的值:
- private List<UC_FoodItem> _items = new List<UC_FoodItem>();
- public List<UC_FoodItem> Items
- {
- get => _items;
- set => SetProperty(ref _items, value);
- }
- protected void LoadFoods()
- {
- try
- {
- DataTable dt = _sqliteHelper.RunToDataSet("select * from Notes order by ID desc").Tables[];
- var items = new List<UC_FoodItem>();
- foreach (DataRow row in dt.Rows)
- {
- UC_FoodItem foodItem = new UC_FoodItem();
- foodItem.lab_id.Content = row["ID"].ToString();
- foodItem.lab_foodName.Content = row["Title"].ToString();
- foodItem.lab_foodPrice.Content = row["Type"].ToString();
- foodItem.lab_foodIntro.Content = row["Content"].ToString();
- items.Add(foodItem);
- }
- Items = items;
- }
- catch (Exception ex)
- {
- Console.WriteLine(ex);
- MessageBox.Show($"载入数据出错:{ex.Message}");
- }
- }
ViewModel 中的绑定属性使用了 INotifyPropertyChanged 模式,此处是使用了 Prism 框架的写法(VM 继承了 BindableBase 类)。然后注意到这里新建了一个局部变量 items,填充完数据才赋值给 Items,这并不是多此一举,因为不这样的话,该属性的改变状态(PropertyChangedCallback)就无法触发。
最后但同样重要的是:既然这个用户控件这么简单,为什么不直接把里面的内容包括依赖属性写在使用的页面呢?因为那样的话,由于 MVVM
模式的原因,页面的 DataContext 已经指定为相关的 ViewModel 了,那么写在后台的依赖属性就找不到 DataContext 了。
WPF 用户控件的自定义依赖属性在 MVVM 模式下的使用备忘的更多相关文章
- 创建WPF用户控件
wpf用户自定义控件和winform创建方法类似,这里先纠正一个误区,就是有很多人也是添加,然后新建,然后是新建用户控件库,但是为什么编译好生成后Debug目录下还是只有exe文件而没有dll文件呢? ...
- WPF Label控件在数据绑定Content属性变化触发TargetUpdated事件简单实现类似TextChanged 事件效果
原文:WPF Label控件在数据绑定Content属性变化触发TargetUpdated事件简单实现类似TextChanged 事件效果 本以为Label也有TextChanged 事件,但在使 ...
- 【demo练习四】:WPF用户控件案例
首先,新建vs中“用户控件(WPF)”,右键项目名 =>"添加"按钮 => 选择“新建项”. 然后选择“用户控件(WPF)” => 起名字 => 点击“添加 ...
- c# 用户控件,usercontrol,自定义控件属性
1.C#用户控件的使用 2.拖动添加:画面上如需多个usercontrol,添加TableLayoutPanel,然后在工具箱中找到usercontrol,拖到相应框中 3.代码添加:主窗口中有多个T ...
- asp.net读取用户控件,自定义加载用户控件
1.自定义加载用户控件 ceshi.aspx页面 <html> <body> <div id="divControls" runat="se ...
- WPF 用户控件嵌入网页
WPF使用用户控件嵌入网页,直接使用WebBrowser或Frame会产生报错,报错信息如下: 1.使用WebBrowser,<WebBrowser Source="http://19 ...
- WPF用户控件库 嵌入外部(VLC)exe
综合网上资源完成的自己的第一篇博客 ------------------------------------------------------------------------ 网上类似的贴子挺多 ...
- [Silverlight]监听指定控件(FrameworkElement)的依赖属性(DependencyProperty)的更改
前言 转载请注明出处:http://www.cnblogs.com/ainijiutian 最近在silverlight项目使用Telerik的控件,遇到一个问题.就是使用RadBusyIndicat ...
- WPF之路——用户控件对比自定义控件UserControl VS CustomControl)
将多个现有的控件组合成一个可重用的“组”. 由一个XAML文件和一个后台代码文件. 不能使用样式和模板. 继承自UserControl类. 自定义控件(扩展) 在现有的控件上进行扩展,增加一些新的属性 ...
随机推荐
- Golang 基础语法介绍及对比(二)
传值与传参 Golong func main() { a := fmt.Println("a = ", a) // 应该输出 "a= 3" a1 := add1 ...
- Github库名命名规范
必要性说明 由于迁移到Github上的项目越来越多,对项目的管理越来越困难.由于各项目命名具有随意性,用之代表git仓库名后就很难快速回忆起这个项目的相关细节,通常需要不断打开某个库才能有所了解.因此 ...
- 刷完欧拉计划中难度系数为5%的所有63道题,我学会了Rust中的哪些知识点?
我为什么学Rust? 2019年6月18日,Facebook发布了数字货币Libra的技术白皮书,我也第一时间体验了一下它的智能合约编程语言MOVE,发现这个MOVE是用Rust编写的,看来想准确理解 ...
- WebStorm开发Vue自定义标签提示是未知标签解决办法
打开 File -> Settings -> File Types 在右侧的窗口中找到Vue.js Template 并选中,在下面的窗口中添加 *.vue 即可解决问题. 修改后
- 《Interest Rate Risk Modeling》阅读笔记——第三章:拟合期限结构
目录 第三章:拟合期限结构 思维导图 扩展 第三章:拟合期限结构 思维导图 扩展 NS 模型的变种
- PHP接口并发测试的方法
PHP接口并发测试的方法 <pre> header('Content-type:text/html; Charset=utf-8'); $uri = "输入你的url" ...
- IntelliJ IDEA 创建java application
1.打开IntelliJ IDEA,选择File——New——Project... 2.选择左侧的java,然后在右侧的Project SDK 中添加 java 环境目录,点击Next 3. 在下面的 ...
- Window与Document
Window 表示一个包含DOM文档的窗口,其 document 属性指向窗口中载入的 DOM文档.使用 document.defaultView 属性可以获取指定文档所在窗口.window作为全局变 ...
- 聊聊Lambda架构
定义 在数据分析场景中,我们可能会遇到这样的问题.例如,我们要做一个推荐系统,如果我们用批处理任务去做,一天或者一小时的推荐频次明显延迟太大.如果用流处理任务,虽然延迟的问题解决了,然而只用实时数据而 ...
- hadoop格式化:java.io.IOException: Incompatible clusterIDs in /home/lxh/hadoop/hdfs/data: namenode clusterID
1 概述 解决hadoop启动hdfs时,datanode无法启动的问题.错误为: java.io.IOException: Incompatible clusterIDs in /home/lxh ...