WPF MVVM基础教程(五)RelativeSource属性绑定

news/2025/2/15 3:06:31/

RelativeSource属性绑定

  • 介绍
  • RelativeSource属性介绍
    • RelativeSource的Mode属性有四种模式:
  • 四种模式用法
    • Self模式
    • FindAncestor模式
      • 使用规则:
    • TemplatedParent模式
    • PreviousData模式
  • 特殊用法
      • 绑定到其他ViewModel上的命令

介绍

RelativeSource 是一个标记扩展,扩展描述相对于绑定目标位置的绑定源位置。

RelativeSource 作用是改变绑定指向的源,默认使用绑定的源是对应的DataContext对象中的属性,如果想要绑定源为其他元素,比如自身、其他父级控件、其他ViewModel,就需要用RelativeSource 进行标记。它表示在绑定表达式中引用另一个元素的属性。它使开发人员可以根据元素的位置和类型来查找绑定源。

RelativeSource属性介绍

属性解释
AncestorLevel以 FindAncestor 模式获取或设置要查找的上级级别。 使用 1 指示最靠近绑定目标元素的项。
AncestorType指定查找的上级节点的类型。
Mode获取或设置 RelativeSourceMode 值,该值描述相对于绑定目标的位置的绑定源的位置。Mode属性是一个RelativeSourceMode 枚举
PreviousData一个静态值,效果等同于 Mode=PreviousData。该值用于返回为 RelativeSource 模式构造的 PreviousData。
Self一个静态值,效果等同于 Mode=Self。该值用于返回为 RelativeSource 模式构造的 Self。
TemplatedParent一个静态值,效果等同于 Mode=TemplatedParent。该值用于返回为 RelativeSource 模式构造的 TemplatedParent。

RelativeSource的Mode属性有四种模式:

RelativeSource属性有四种模式:

  1. FindAncestor:查找指定类型的父元素,和 AncestorType 或 AncestorLevel 一起使用。
  2. PreviousData:使用数据提供程序中的前一个数据项。
  3. Self:使用当前元素。
  4. TemplatedParent:查找元素的模板父级。

四种模式用法

Self模式

绑定控件本身的属性

示例:

实现正方形控件(宽和高相等),通过RelativeSource 实现,使用Self将Width绑定到Height上。

Width="{Binding RelativeSource={RelativeSource Self}, Path=Height}"//或者
Width="{Binding RelativeSource={RelativeSource Mode=Self}, Path=Height}"

控件的Xaml代码:

 <ButtonWidth="{Binding RelativeSource={RelativeSource Mode=Self}, Path=Height}"Height="100"Margin="40,67,0,0"HorizontalAlignment="Left"VerticalAlignment="Top"Content="Button"/>

效果:

只需要修改Height值,Width就会跟着变化

在这里插入图片描述

FindAncestor模式

绑定控件父元素及更上一级的元素,使用Mode=FindAncestor和AncestorType 、 AncestorLevel配合实现。

使用规则:

  1. 必须要设置AncestorType 属性,只要设置了Mode=FindAncestorAncestorLevel值,就必须要设置AncestorType 属性,否则会报错。
  2. 如果未显式设置属性 Mode,则设置AncestorTypeAncestorLevel属性会将属性值隐式锁定 Mode 为 FindAncestor。(Mode=FindAncestor可省略)
  3. AncestorLevel设置为1就是默认找到的第一个指定类型的父元素,2就是第二个
  4. 绑定成功的还有一点,对应父元素相关属性必须有值,如果对应父元素对应属性无值,则无效果。

如下几种定义效果是相同的

RelativeSource={RelativeSource Mode=FindAncestor, AncestorLevel=1, AncestorType=Grid}
RelativeSource={RelativeSource AncestorLevel=1, AncestorType=Grid}
RelativeSource={RelativeSource AncestorType=Grid}

示例:

通过设置一个Button的Width和不同父级布局控件的宽度绑定来演示FindAncestor模式
在这里插入图片描述

当前界面代码:

<Windowx:Class="WpfRelativeSourceExample.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:local="clr-namespace:WpfRelativeSourceExample"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"Title="MainWindow"Width="800"Height="450"mc:Ignorable="d"><Grid><StackPanel Background="LightGray"><GridWidth="768"Height="380"Margin="0,27,0,0"HorizontalAlignment="Left"Background="Gray"><GridWidth="396"Height="344"Margin="0,36,0,0"HorizontalAlignment="Left"VerticalAlignment="Top"Background="Linen"><Canvas Margin="0,53,173,0" Background="DarkCyan" ><ButtonCanvas.Top="56"Height="100"HorizontalAlignment="Center"VerticalAlignment="Top"Content="Button" /></Canvas></Grid></Grid></StackPanel></Grid>
</Window>

将Button的Width设置和Canvas一样,增加下面的绑定

Width="{Binding Width, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Canvas}}"

此时并未生效

在这里插入图片描述

因为规则4中说明对应Canvas未定义,对应的Width属性,所有无法生效,只要对应Canvas设置了Width属性,RelativeSource就生效了。

增加Width

然后依次跟上面两级的Grid的绑定

第一级:

  <ButtonCanvas.Top="56"Width="{Binding Width, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Grid}}"Height="100"HorizontalAlignment="Center"VerticalAlignment="Top"Content="Button" />//等效                    
<ButtonCanvas.Top="56"Width="{Binding Width, RelativeSource={RelativeSource Mode=FindAncestor, AncestorLevel=1, AncestorType=Grid}}"Height="100"HorizontalAlignment="Center"VerticalAlignment="Top"Content="Button" />

在这里插入图片描述

第二级:

<ButtonCanvas.Top="56"Width="{Binding Width, RelativeSource={RelativeSource Mode=FindAncestor, AncestorLevel=2, AncestorType=Grid}}"Height="100"HorizontalAlignment="Center"VerticalAlignment="Top"Content="Button" />

在这里插入图片描述

TemplatedParent模式

TemplatedParent模式主要用在重写或者定义控件模板Template中,用于将模板中的属性和控件本身的属性绑定,类似TemplateBinding,可以对TemplateBinding进行扩展,利用Converter实现一些TemplateBinding不支持的属性绑定

示例:

 <ButtonMargin="49,60,0,0"Padding="10"HorizontalAlignment="Left"VerticalAlignment="Top"Content="Button"><Button.Style><Style TargetType="Button"><Setter Property="Template"><Setter.Value><ControlTemplate TargetType="Button"><Border Background="{TemplateBinding Background}"><ContentPresenter Margin="{Binding Path=Padding, RelativeSource={RelativeSource TemplatedParent}}" Content="{TemplateBinding Content}" /></Border></ControlTemplate></Setter.Value></Setter></Style></Button.Style></Button>

PreviousData模式

PreviousData可以在数据绑定表达式中使用前一个数据项。通常在ItemsControl中使用,用于根据前一个项的属性计算当前项的属性。PreviousData只能在ItemsControl或其派生类中使用。

使用场景,暂无示例

特殊用法

使用RelativeSource改变绑定的ViewModel对象。在嵌套的ViewModel中,命令一定要写在对应的VIewModel(或者Model)中才能实现绑定,这时可以通过RelativeSource绑定到其父级的ViewModel中的命令上。

比如在DataGrid列中有按钮事件,就必须对应的命令需要写在对应的Model中增加命令

正常下一个DataGird(在用户控件UserManageUC.xaml中)

<DataGridWidth="605"Height="341"Margin="59,74,0,0"HorizontalAlignment="Left"VerticalAlignment="Top"AutoGenerateColumns="False"ItemsSource="{Binding Users}"><DataGrid.Columns><DataGridTextColumn Binding="{Binding Id}" Header="序号" /><DataGridTextColumn Binding="{Binding Name}" Header="姓名" /><DataGridTextColumn Binding="{Binding Age}" Header="年龄" /><DataGridTemplateColumn Header="操作"><DataGridTemplateColumn.CellTemplate><DataTemplate><StackPanel Orientation="Horizontal"><Button Command="{Binding ModifyCmd}" Content="修改" /><Button Content="删除" /></StackPanel></DataTemplate></DataGridTemplateColumn.CellTemplate></DataGridTemplateColumn></DataGrid.Columns></DataGrid>

对应的数据模型UserModel

 public class UserModel{public int Id { get; set; }public string Name { get; set; }public int Age { get; set; }public CommandBase ModifyCmd{get{return new CommandBase(o =>{MessageBox.Show($"UserModel Modify:{Name}");});}}}
}

在对应的ViewModel创建集合并初始化

public class UserManageUCViewModel : ViewModelBase{public ObservableCollection<UserModel> Users{ get; set; }public UserManageUCViewModel(){Users= new ObservableCollection<UserModel>();Users.Add(new UserModel() { Id=1,Name="张三",Age=11});Users.Add(new UserModel() { Id=2,Name="李四",Age=22});}}

此时效果,正常使用命令

在这里插入图片描述

绑定到其他ViewModel上的命令

在UserManageUCViewModel 上添加命令

public CommandBase ModifyCmd
{get{return new CommandBase(o =>{var user=o as UserModel;MessageBox.Show($"UserManageUCViewModel Modify:{user.Name}");});}
}

改变按钮Command的绑定,使用RelativeSource的FindAncestor模式RelativeSource={RelativeSource AncestorType=local:UserManageUC}帮绑定对象改为UserManageUC用户控件,然后目标改为DataContext.ModifyCmd,然后增加CommandParameter,将该行绑定的数据作为命令参数传入

  <ButtonCommand="{Binding DataContext.ModifyCmd, RelativeSource={RelativeSource AncestorType=local:UserManageUC}}"CommandParameter="{Binding}"Content="修改" />

效果:
在这里插入图片描述


http://www.ppmy.cn/news/67288.html

相关文章

KU地址提供》什么是HTML 标签

HTML 标签 下拉选单- select 单选选单 下拉式选单让使用者可以从一堆选项中选择出一个(或多个)选项【KU地址K͜W͜9㍠N͜E͜T͜娜娜提供】。本身做为选单的容器&#xff0c;在select 里面用标签来建立个别选项。 <select><option value"dog" selected>…

内网渗透—域环境之信息收集

内网渗透—域环境之信息收集 1. 前言2. 关于域2.1. 域搭建2.2. 域渗透思路 3. 域信息收集3.1. 判断是否存在域3.1.1. 查询网络信息3.1.2. 查询当前登录域与域环境3.1.3. 判断主域 3.2. 查找域控制器3.2.1. 查询DNS地址3.2.2. 查看域控制器的机器名3.2.3. 查看域控制器 3.3. 获取…

fork+父子进程在理解+进程控制

索引 fork父子进程在理解进程控制1.进程终止2.进程等待3.获取进程状态Status fork父子进程在理解 fork之后&#xff0c;内核做了什么&#xff1f; 将分配新的内存块和内核数据结构给子进程将父进程部分数据结构拷贝至子进程添加子进程到系统列表中fork返回开始调度器调度 fo…

springboot常用注解汇总

一. 控制器相关注解 RestController&#xff1a; 表示该类是一个 RESTful Web 服务的控制器&#xff0c;将返回值转换成 JSON 格式并响应给客户端 RequestMapping&#xff1a; 映射请求的 URL 地址和方法&#xff0c;用在类或方法上&#xff0c;可以设置 URL 地址、请求方法、…

离散对数介绍

前置知识 欧拉函数 ϕ ( n ) \phi(n) ϕ(n) 欧拉函数简介 阶 若 g g g和 n n n互质&#xff0c;则令 g x % n 1 g^x\%n1 gx%n1的最小正整数 x x x称为 g g g模 n n n的阶。 原根 对于互质的两个正整数 g g g和 n n n&#xff0c;如果 g g g模 n n n的阶为 ϕ ( n ) \phi…

《c++ primer笔记》第十四章 重载运算与类型转换

文章目录 一、基本概念二、输入和输出运算符2.1重载输出运算符<<2.2重载输入运算符>> 三、算术和关系运算符四、赋值运算符五、下标运算符六、递增和递减运算符七、成员访问运算符八、函数调用运算符8.1lamba函数对象8.2标准库定义的函数对象8.3可调用对象与functi…

安装nvm,解决访问raw.githubusercontent.com出现refused拒绝连接错误

具体的错误信息如下&#xff1a; curl: (7) Failed to connect to raw.githubusercontent.com port 443: 拒绝连接 查询了一下发现是dns污染的问题&#xff0c;设置直连 vi /etc/hosts ###增加下面的解析 199.232.68.133 raw.githubusercontent.com 199.232.68.133 user-ima…

android使用MediaPlayer播放raw目录下的mp3

使用android自带的 MediaPlayer 播放 mp3 时&#xff0c;需要注意的几个点&#xff1a; 1. 使用&#xff1a; ——>初始化&#xff1a; MediaPlayer mediaPlayer MediaPlayer.create(this, R.raw.example_song); ——>播放: mediaPlayer.start(); ——>释放&am…