WPF 用户控件的自定义依赖属性在 MVVM 模式下的使用备忘

时间:2022-09-04 07:26:56

依赖属性相当于扩充了 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&num; 用户控件,usercontrol&comma;自定义控件属性

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

  5. asp&period;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. &lbrack;Silverlight&rsqb;监听指定控件&lpar;FrameworkElement&rpar;的依赖属性&lpar;DependencyProperty&rpar;的更改

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

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

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

随机推荐

  1. IOS手动添加CoreData

    手动添加coreData: 1.在target-build phrase-Link binary with libraries里增加CoreData Framework 2.加入数据模型:comman ...

  2. 修改win10打开文件资源管理器

  3. CFX客户端调用报错

    Exception in thread "main" javax.xml.ws.soap.SOAPFaultException: Unmarshalling Error: unex ...

  4. final修饰符&comma;finally&comma;finalize区别

    1.final 如果一个类被声明为final,意味着它不能再派生出新的子类,不能作为父类被继承.因此,一个类不能即被声明为abstract,又被声明为final.将变量或方法声明为final,可以保证 ...

  5. 最新版spark1&period;1&period;0集群安装配置

    和分布式文件系统和NoSQL数据库相比而言,spark集群的安装配置还算是比较简单的: 很多教程提到要安装java和scala,但我发现spark最新版本是包含scala的,JRE采用linux内嵌的 ...

  6. SharePoint 2010 PowerShell 系列 之 备份、还原、部署 &period;WSP

    转:http://www.cnblogs.com/Fengger/archive/2012/08/24/2654093.html PowerShell系列目录 最近在部署测试环境,就顺便把PowerS ...

  7. Hard 计算0到n之间2的个数 &commat;CareerCup

    一种是Brute force,O(nlogn) 另一种是找规律O(n),见http://hawstein.com/posts/20.4.html 当某一位的数字小于2时,那么该位出现2的次数为:更高位 ...

  8. mysql与java数据类型对应关系

  9. JQuery - MD5加密

    效果: JS代码: 命名为任意名称,一般为:Jquery.md5.js /** * jQuery MD5 hash algorithm function * * <code> * Calc ...

  10. HTTP认证方式详解

    HTTP请求报头: Authorization HTTP响应报头: WWW-Authenticate   HTTP认证 基于 质询 /回应( challenge/response)的认证模式.   ◆ ...