首页 > 其他分享 >.NET|--WPF|--笔记合集|--依赖项属性|--5.附加属性

.NET|--WPF|--笔记合集|--依赖项属性|--5.附加属性

时间:2024-09-29 21:24:21浏览次数:6  
标签:-- System 附加 Windows DockPanel NET public 属性

前言


附加属性是一个 Extensible Application Markup Language (XAML) 概念。 

附加属性允许为派生自 DependencyObject 的任何 XAML 元素设置额外的属性/值对,即使该元素未在其对象模型中定义这些额外的属性。 
额外的属性可进行全局访问。 
附加属性通常定义为没有常规属性包装器的依赖属性的专用形式。

附加属性 Vs 依赖项属性

附加属性是 XAML 概念,依赖属性是 WPF 概念。 

在 WPF 中,WPF 类型上大多数与 UI 相关的附加属性都作为依赖属性实现。 
作为依赖属性实现的 WPF 附加属性支持依赖属性概念,例如包含元数据中的默认值的属性元数据。

附加属性是一种依赖项属性, 由WPF属性系统管理.
不同之处在于附加属性被应用到的类, 并非定义附加属性的那个类.

# 比如, 下面的例子, 套入DockPanel和TextBox来解读下就是
# 不同之处在于(DockPanel的)附加属性被应用到的类(TextBox),并非定义附加属性的那个类(DockPanel).

<DockPanel>
    <TextBox DockPanel.Dock="Top">Enter text</TextBox>
</DockPanel>

附加属性用法模型

附加属性的设定虽然可以为各种对象赋值,但这并不一定会产生具体的结果,也不一定会被其他对象使用。附加属性的主要目的是为来自各种类层次和逻辑关系的对象提供一种方法,将公共信息报告给定义附加属性的类型。附加属性的使用通常遵循以下三种模式:

  1. 父元素模式:定义附加属性的类型是为附加属性设置值的元素的父级。
    父类型通过作用于对象树结构的内部逻辑,循环访问其子对象,获取值,并以某种方式处理这些值。

  2. 子元素模式:定义附加属性的类型作为各种可能的父元素和内容模型的子元素。

  3. 服务模式:定义附加属性的类型表示一种服务。其他类型为该附加属性设置值,然后,当在服务的上下文中计算设置该属性的元素时,通过服务类的内部逻辑获取附加属性的值。

总之,附加属性的使用遵循这三种模式,才能发挥其作用。

父类型模式举例
<DockPanel>
<TextBox DockPanel.Dock="Top">Enter text</TextBox>
</DockPanel>

# DockPanel的源码
[CommonDependencyProperty]
public static readonly DependencyProperty DockProperty;

static DockPanel()
{
   // 省略...
    DockProperty = DependencyProperty.RegisterAttached("Dock", typeof(Dock), typeof(DockPanel), new FrameworkPropertyMetadata(Dock.Left, OnDockChanged), IsValidDock);        
}

// 定义附加属性的类型(DockPanel)是为附加属性(DockProperty)设置值的元素(TextBox)的父级...

// 重点是分清父子关系, 该例子中, 父级是DockPanel, 子级是TextBox, 附加属性Dock, 定义在父级DockPanel类中, 该模式为父类型模式.

子元素模式
<!-- TextElement.FontSize -->

<!--可以简略这么写:<StackPanel TextElement.FontSize="20">, 但是这么写,不容易看出TextElement为StackPanel的子元素.-->
<StackPanel >
    <!--定义附加属性(FontSize)的类型(TextElement)作为各种可能的父元素(StackPanel)的子元素。-->
    <TextElement.FontSize>
        20
    </TextElement.FontSize>

    <!--单一内容模型的控件只能包含一个子元素。例如 Button、ContentControl 和 Label。-->
    <Button TextElement.FontSize="10" Content="定义附加属性的类型(TextElement)作为各种可能的父元素和内容模型的子元素。"/>

    <!--如果上面的Button看着不太好理解, 换为下种表达方式可能会更好看出来TextElement作为内容模型Button的子元素-->
    <Button>
        <TextElement.FontSize>
            10
        </TextElement.FontSize>
        <Button.Content>
            定义附加属性(FontSize)的类型(TextElement)作为各种可能的内容模型(Button)的子元素。
        </Button.Content>
    </Button>

    <TextBlock>FontSize为20, 继承自StackPanel</TextBlock>
</StackPanel>
// TextElement源码

[CommonDependencyProperty]
public static readonly DependencyProperty FontFamilyProperty;



static TextElement()
{      
    FontSizeProperty = DependencyProperty.RegisterAttached("FontSize", typeof(double), typeof(TextElement), new FrameworkPropertyMetadata(SystemFonts.MessageFontSize, FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.Inherits), IsValidFontSize);

}
        
// 定义附加属性的类型(TextElement)作为各种可能的父元素和内容模型的子元素。
// 这段不太懂, 又是父元素, 又是子元素的~

// 我本来的断句是
// 定义附加属性的类型(TextElement) / 作为各种可能的父元素 / 和 / 内容模型的子元素。

// 正确的断句应该是↓?
// 定义附加属性的类型(TextElement) / 作为各种可能的 / 父元素和内容模型的 / 子元素。


// 重点是分清父子关系, 该例子中, 父级是StackPanel, 子级是TextBox, 附加属性Dock, 定义在父级DockPanel类中, 该模式为父类型模式.

服务模式

WPF的拖放操作中使用附加属性存储和传递数据。
例如,DragDrop类定义了一些附加属性,
如DragDrop.DataContextProperty,用于在拖放过程中存储和获取数据。

在这个例子中,DragDrop类通过附加属性存储拖动的数据,
当放下数据时,通过Drop事件处理程序访问这些数据。

<!-- Drop="Window_Drop" -->
<Window x:Class="WpfApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="200" Width="300"
        AllowDrop="True"
        Drop="Window_Drop">
    <Grid>
        <TextBlock Text="拖动一些文本到这里" HorizontalAlignment="Center" VerticalAlignment="Center"/>
    </Grid>
</Window>

// MainWindow.xaml.cs
using System.Windows;

namespace WpfApp
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Window_Drop(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.Text))
            {
                string droppedText = (string)e.Data.GetData(DataFormats.Text);
                MessageBox.Show($"你拖放了: {droppedText}");
            }
        }
    }
}
总结 : 
其实这3中模式, 服务模式比较好辨认, 在"父元素模式"和"子元素模式"哪里, 其实我还是懵了一下, , , 

XAML附加属性 Vs 代码实现附加属性

<!-- xaml中附加属性使用 -->
<DockPanel>
<TextBox DockPanel.Dock="Top">Enter text</TextBox>
</DockPanel>
// LINQPad中实现

void Main()
{

	System.Windows.Application app = new System.Windows.Application();
	var mainWindow = new MainWindows
	{
		Title = "依赖项属性-附加属性-DockPanel演示",
		Width = 400,
		Height = 250,
		WindowStartupLocation = System.Windows.WindowStartupLocation.CenterScreen
	};
	app.Run(mainWindow);
}

// 主窗口
public class MainWindows : System.Windows.Window
{
	public MainWindows()
	{
		Init();
	}

	public void Init()
	{
		// 创建 DockPanel 实例
		DockPanel dockPanel = new DockPanel();
		// 创建 TextBox 实例
		TextBox textBox = new TextBox
		{
			Text = "Enter text"
		};
		// 将 TextBox 的 DockPanel.Dock 属性设置为 Top
		DockPanel.SetDock(textBox, Dock.Top);
		// 将 TextBox 添加到 DockPanel 中
		dockPanel.Children.Add(textBox);
		// 将 DockPanel 设置为窗口的内容
		this.Content = dockPanel;
	}
}

附加属性--创建

// LINQPad中可以运行
void Main()
{

	System.Windows.Application app = new System.Windows.Application();
	var mainWindow = new MainWindows
	{
		Title = "依赖项属性-附加属性-DockPanel演示",
		Width = 400,
		Height = 250,
		WindowStartupLocation = System.Windows.WindowStartupLocation.CenterScreen
	};
	app.Run(mainWindow);
}

// 主窗口
public class MainWindows : System.Windows.Window
{
	public MainWindows()
	{
		Init();
	}

	public void Init()
	{
		// 创建 TextBox 实例
		System.Windows.Controls.TextBox textBox = new System.Windows.Controls.TextBox
		{
			Text = "演示创建附加属性, 以及设置/获取, 附加属性得值\r\n"
		};
		// 将 TextBox 的 DockPanel.Dock 属性设置为 Top
		System.Windows.Controls.DockPanel.SetDock(textBox, System.Windows.Controls.Dock.Top);


		Aquarium aquarium = new Aquarium();

		textBox.Text += ($"Aquarium.Fish.默认值为:{Aquarium.GetHasFish(textBox)}\r\n");


		Aquarium.SetHasFish(textBox, true);
		textBox.Text += ($"Aquarium.Fish.设置为:{Aquarium.GetHasFish(textBox)}\r\n");

		// 感兴趣得可以看一下,如何会根据设置得Dock, 而显示得位置不同~
		textBox.Text += ($"但是是不是感觉哪里不对?只是设置了值,但是并没有具体得业务逻辑,比如DockPanel设置了Dock.Top,就会显示在Top.\r\n咱们这里只是演示,设置了true,打印出来true即可...\r\n");
		this.Content = textBox;
	}
}
// 官方示例

标签:--,System,附加,Windows,DockPanel,NET,public,属性
From: https://www.cnblogs.com/love-zf/p/18440771

相关文章

  • 树分治
    点分治点分治适合处理大规模的树上路径信息问题。本质思想是选择一点作为分治中心,将原问题划分为几个相同的子树上的问题,进行递归解决。常见的用于统计树上有关路径的信息。假设当前选定根节点为\(rt\),则符合条件的路径必然是以下两种之一:经过\(rt\)或一段在\(rt\)上;在......
  • 虚拟机端口映射到本机端口(超详细)
    应用场景:在工作或者学习中,我们和我们的团队都是处在一个局域网中的,为了某些业务,我们会在自己的本机安装虚拟机,比如我们会安装一台linux虚拟机作为服务器,在服务器上搭建对应的服务,这时候需要团队都能访问到你的虚拟机,但很明显,如果我们用的NAT模式的话,我们的虚拟......
  • Netflix截屏录屏播放的视频黑屏技术原理
    数字版权管理(DigitalRightsManagement,DRM)奈飞(Netflix)等流媒体平台对截屏或录屏时显示黑屏的现象,主要是通过数字版权管理(DigitalRightsManagement,DRM)技术实现的。技术原理:DRM保护:奈飞使用了名为Widevine或PlayReady等DRM技术,这些技术确保在播放受版权保护的内容时,限制......
  • 基于正则化的多任务联邦
    1.导言现在多任务学习根据实现方法可以粗略地被分为两种,一个是基于神经网络的多任务学习[1][2][3][4],这种多任务学习在CV和NLP取得了大量的应用。 基于神经网络的多任务学习然而我们最根溯源,其实多任务学习最开始并不是基于神经网络的,而是另一种经典的方法——基于正则表示......
  • Halcom与C#窗口应用联合问题一:DLL“halcon”:找不到指定的模块。
     问题如下:原因是:        如果你在解决方案资源管理器中的引用下添加了halcondotnet.dll文件,有可能在工具箱下没有自动添加。在工具箱项里面没有HWindowControl工具。解决方法如下:                1.在工具箱中右击任何一个工具,然后点击......
  • 法定每月计薪天数 vs 法定每月工作天数 All In One
    法定每月计薪天数vs法定每月工作天数AllInOne法定每月记薪天数21.75天/月,用于计算工资的发放,缺勤、事假的工资扣除(365-104-11)/12//20.833333333333332(365-115)/12//20.833333333333332法定每月工作天数20.83天/月,用于计算加班时长、加班费......
  • 大模型学习路线:这会是你见过最全最新的大模型学习路线【2024最新】
    大模型学习路线建议先从主流的Llama开始,然后选用中文的Qwen/Baichuan/ChatGLM,先快速上手体验prompt工程,然后再学习其架构,跑微调脚本如果要深入学习,建议再按以下步骤,从更基础的GPT和BERT学起,因为底层是相通的,而且实际落地到一个系统中,应该也是大模型结合小模型(大模型在做判......
  • c语言实现:链表创建、插入、删除、翻转
    #include<stdio.h>#include<stdlib.h>//链表创建typedefstructNode{intdata;structNode*next;}Node;//创建一个节点Node*createNode(intdata){Node*newNode=(Node*)malloc(sizeof(Node));newNode->data=data;newNode......
  • Jupyter - autoreload
     %reload_extautoreload%autoreload2 Usage¶Thefollowingmagiccommandsareprovided:%autoreload, %autoreload nowReloadallmodules(exceptthoseexcludedby %aimport)automaticallynow.%autoreload 0, %autoreload offDisableautomatic......
  • 基于OpenCV的实时年龄与性别识别(支持CPU和GPU)
    关于深度实战社区我们是一个深度学习领域的独立工作室。团队成员有:中科大硕士、纽约大学硕士、浙江大学硕士、华东理工博士等,曾在腾讯、百度、德勤等担任算法工程师/产品经理。全网20多万+粉丝,拥有2篇国家级人工智能发明专利。社区特色:深度实战算法创新获取全部完整项目......