依赖属性相当于扩充了 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)设置需要绑定的值:

C#
 
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 模式下的使用备忘的更多相关文章

  1. 创建WPF用户控件

    wpf用户自定义控件和winform创建方法类似,这里先纠正一个误区,就是有很多人也是添加,然后新建,然后是新建用户控件库,但是为什么编译好生成后Debug目录下还是只有exe文件而没有dll文件呢? ...

  2. WPF Label控件在数据绑定Content属性变化触发TargetUpdated事件简单实现类似TextChanged 事件效果

    原文:WPF Label控件在数据绑定Content属性变化触发TargetUpdated事件简单实现类似TextChanged 事件效果   本以为Label也有TextChanged 事件,但在使 ...

  3. 【demo练习四】:WPF用户控件案例

    首先,新建vs中“用户控件(WPF)”,右键项目名 =>"添加"按钮 => 选择“新建项”. 然后选择“用户控件(WPF)” => 起名字 => 点击“添加 ...

  4. c# 用户控件,usercontrol,自定义控件属性

    1.C#用户控件的使用 2.拖动添加:画面上如需多个usercontrol,添加TableLayoutPanel,然后在工具箱中找到usercontrol,拖到相应框中 3.代码添加:主窗口中有多个T ...

  5. asp.net读取用户控件,自定义加载用户控件

    1.自定义加载用户控件 ceshi.aspx页面 <html> <body> <div id="divControls" runat="se ...

  6. WPF 用户控件嵌入网页

    WPF使用用户控件嵌入网页,直接使用WebBrowser或Frame会产生报错,报错信息如下: 1.使用WebBrowser,<WebBrowser Source="http://19 ...

  7. WPF用户控件库 嵌入外部(VLC)exe

    综合网上资源完成的自己的第一篇博客 ------------------------------------------------------------------------ 网上类似的贴子挺多 ...

  8. [Silverlight]监听指定控件(FrameworkElement)的依赖属性(DependencyProperty)的更改

    前言 转载请注明出处:http://www.cnblogs.com/ainijiutian 最近在silverlight项目使用Telerik的控件,遇到一个问题.就是使用RadBusyIndicat ...

  9. WPF之路——用户控件对比自定义控件UserControl VS CustomControl)

    将多个现有的控件组合成一个可重用的“组”. 由一个XAML文件和一个后台代码文件. 不能使用样式和模板. 继承自UserControl类. 自定义控件(扩展) 在现有的控件上进行扩展,增加一些新的属性 ...

随机推荐

  1. Codeforces Round 584 题解

    -- A,B 先秒切,C 是个毒瘤细节题,浪费了很多时间后终于过了. D 本来是个 sb 题,然而还是想了很久,不过幸好没什么大事. E1,看了一会就会了,然而被细节坑死,好久才过. 感觉 E2 很可 ...

  2. Web协议详解与抓包实战:HTTP1协议-请求与响应的上下文(7)

    一.请求的上下文: User-Agent 指明客户端的类型信息,服务器可以据此对资源的表述做抉择 二.请求的上下文: Referer 浏览器对来自某一页面的请求自动添加的头部 截图2 这对于我们的防盗 ...

  3. [LeetCode] 926. Flip String to Monotone Increasing 翻转字符串到单调递增

    A string of '0's and '1's is monotone increasing if it consists of some number of '0's (possibly 0), ...

  4. [LeetCode] 454. 4Sum II 四数之和之二

    Given four lists A, B, C, D of integer values, compute how many tuples (i, j, k, l) there are such t ...

  5. 使用VUECLI3

    $ yarn global add @vue/cli // OR $ npm install @vue/cli -g 然后在加入下面的代码 $ vue create my-app $ cd my-ap ...

  6. 创建简单Maven项目

    目录: Maven基础构建概念.仓库.构建与部署 Maven作用 Maven项目install Maven安装配置.目录结构.配置文件 配置Maven默认本地仓库 Maven常见命令 使用Maven ...

  7. MySQL常用系统表汇总

    在这篇文章中: MySQL5.7 默认模式 Information_schema performance_schema mysql sys MYSQL SHOW 命令 致谢 概述 本篇文章虽大部分内容 ...

  8. Prometheus 编写告警规则案例

    Prometheus 编写告警规则案例 注:确保alertmanager配置完毕! 1.创建编辑文件:vim /usr/local/prometheus/rules/node.yml # groups ...

  9. MySQL使用现状分析与优化

    前言 再紧张的裁员氛围,也不该影响你学习的心态.不要本末倒置,技术永远不会落后,只要你还在学习的道路上,没有后退. 数据库架构 目前生产环境RDS是多区可用架构.数据库实例发生计划内或计划外的中断时, ...

  10. c#语法复习总结(2)-数据类型

    C#数据类型可以分值类型和引用类型.值类型,先说说一个概念 c#栈和堆. 一,栈和堆. 堆:在c里面叫堆,在c#里面其实叫托管堆.为什么叫托管堆,我们往下看. 栈:就是堆栈,因为和堆一起叫着别扭,就简 ...