依赖属性相当于扩充了 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 了。

最新文章

  1. python之路二十
  2. Android:关于声明文件中android:process属性说明
  3. Code First05--CodeFirst中值对象
  4. Windwos服务器远程桌面不能复制粘贴的解决方法
  5. 【整理贴】DBA-常用到的动态视图分析语句
  6. 一条命令使win7可以直接运行.net3.5程序
  7. [maven] 搭建多模块企业级项目
  8. DOM操作 append prependTo after before
  9. audition输出参数设置
  10. shell学习笔记(1):利用IFS打印用户和默认shell
  11. HTTP的长短连接、长短轮询的区别(转载)
  12. 禁用浏览器缓存Ajax请求
  13. Core MVC
  14. ural 1203. Scientific Conference
  15. MSSQL常用函数大全
  16. PICC国际标准ISO14443下载
  17. Linux下MongoDB安装和配置详解
  18. sqlserver2008 批量插入数据
  19. CSS 条件判断、等宽字体以及ch单位
  20. 2、JDBC-CURD

热门文章

  1. MySQL实战45讲学习笔记:第十二讲
  2. [LeetCode] 743. Network Delay Time 网络延迟时间
  3. [LeetCode] 15. 3Sum 三数之和
  4. xshell 与服务器断开连接后 服务停止500internal error
  5. python使用rdflib创建rdf,在jena fuseki上执行SPARQL查询
  6. 从头学一次J2EE笔记
  7. 剑指Offer_Java_顺时针打印矩阵(二维数组)
  8. 排序算法Java代码实现(六)—— 堆排序
  9. axios FastMock 跨域 代理
  10. jquery点击放大图片