WPF attached property register on another static class and used on another class, property changed based on attached property via OnMetdata changed

An Attached Property is a special, XAML-centric concept that is, under the hood, a Dependency Property. It allows a child element to specify a value for a property that is actually defined by its parent element.

Key Characteristics:

  • Defined By: One class (typically a container or service).

  • Used On/Set On: Any other DependencyObject (typically a child element within the defining class).

  • Purpose: To allow a parent to define a "setting" that its children can use. It's a form of context or metadata that a child element receives from its parent.

  • Creation: You RegisterAttached it with the property system.

Common Use Cases:

  • Layout Containers: Grid.RowGrid.ColumnCanvas.LeftDockPanel.Dock.

  • Services: ToolTipService.ToolTipScrollViewer.IsScrollChainingEnabled.

 

 

Dependency Property vs Attached Property

eatureDependency PropertyAttached Property
Definition Defined on and used by the same class. Defined by one class but set on other objects.
Purpose Adds a native, bindable property to a class. Provides a "context property" from a parent to its children.
Registration DependencyProperty.Register DependencyProperty.RegisterAttached
Accessors Standard CLR property wrapper (get/set). Static GetPropertyName and SetPropertyName methods.
XAML Syntax <MyControl MyProperty="Value"/> <ChildElement DefiningClass.PropertyName="Value"/>
Analogy A person's Name. It's a property of the person. A person's Seat Number in a theater. The seat number isn't a property of the person, but is assigned to them by the theater (the container).

 

 

//xaml
<Window x:Class="WpfApp19.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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        WindowState="Maximized"
        xmlns:local="clr-namespace:WpfApp19"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.Resources>
        <Style TargetType="Button" x:Key="StatusButtonStyle">
            <Setter Property="FontSize" Value="100"/>
            <Style.Triggers>
                <Trigger Property="local:StatusService.Status" Value="Normal">
                    <Setter Property="Foreground" Value="Black"/>
                </Trigger>
                <Trigger Property="local:StatusService.Status" Value="Warning">
                    <Setter Property="Foreground" Value="Orange"/>
                </Trigger>
                <Trigger Property="local:StatusService.Status" Value="Error">
                    <Setter Property="Foreground" Value="Red"/>
                </Trigger>
                <Trigger Property="local:StatusService.Status" Value="Success">
                    <Setter Property="Foreground" Value="Green"/>
                </Trigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>
    <StackPanel>
        <Button Content="Normal Button"
                local:StatusService.Status="Normal"
                Style="{StaticResource StatusButtonStyle}"/>
        <Button Content="Normal Button"
                local:StatusService.Status="Warning"
                Style="{StaticResource StatusButtonStyle}"/>
        <Button Content="Normal Button"
                local:StatusService.Status="Error"
                Style="{StaticResource StatusButtonStyle}"/>
        <Button Content="Normal Button"
                local:StatusService.Status="Success"
                Style="{StaticResource StatusButtonStyle}"/>
    </StackPanel>
</Window>


//cs
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace WpfApp19
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
    }

    public static class StatusService
    {
        public static readonly DependencyProperty StatusProperty =
            DependencyProperty.RegisterAttached
            ("Status",
                typeof(string),
                typeof(StatusService),
                new PropertyMetadata("Normal"));

        public static string GetStatus(DependencyObject dObj)
        {
            return (string)dObj.GetValue(StatusProperty);
        }
        
        public static void SetStatus(DependencyObject dObj,object value)
        {
            dObj.SetValue(StatusProperty,value);
        }        
    }
}

 

image

 

 

 

<Window x:Class="WpfApp19.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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        WindowState="Maximized"
        xmlns:local="clr-namespace:WpfApp19"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.Resources>
        <Style TargetType="Button" x:Key="StatusButtonStyle">
            <Setter Property="FontSize" Value="100"/>
        </Style>
    </Window.Resources>
    <StackPanel>
        <Button Content="Normal Button"
                local:StatusService.Status="Normal"
                Style="{StaticResource StatusButtonStyle}"/>
        <Button Content="Normal Button"
                local:StatusService.Status="Warning"
                Style="{StaticResource StatusButtonStyle}"/>
        <Button Content="Normal Button"
                local:StatusService.Status="Error"
                Style="{StaticResource StatusButtonStyle}"/>
        <Button Content="Normal Button"
                local:StatusService.Status="Success"
                Style="{StaticResource StatusButtonStyle}"/>
    </StackPanel>
</Window>


using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace WpfApp19
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
    }

    public static class StatusService
    {
        public static readonly DependencyProperty StatusProperty =
            DependencyProperty.RegisterAttached
            ("Status",
                typeof(string),
                typeof(StatusService),
                new PropertyMetadata("Normal", OnStatusChanged));

        public static string GetStatus(DependencyObject dObj)
        {
            return (string)dObj.GetValue(StatusProperty);
        }

        public static void SetStatus(DependencyObject dObj, object value)
        {
            dObj.SetValue(StatusProperty, value);
        }

        private static void OnStatusChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var btn = d as Button;
            if (btn == null)
            {
                return;
            }

            var status = StatusService.GetStatus(btn);
            switch (status)
            {
                case "Normal":
                    btn.Foreground = new SolidColorBrush(Colors.Red);
                    break;
                case "Warning":
                    btn.Foreground = new SolidColorBrush(Colors.Green);
                    break;
                case "Error":
                    btn.Foreground = new SolidColorBrush(Colors.Blue);
                    break;
                case "Success":
                    btn.Foreground = new SolidColorBrush(Colors.Cyan);
                    break;
            }
        }
    }
}

 

 

 

image

 

posted @ 2025-09-29 18:52  FredGrit  阅读(8)  评论(0)    收藏  举报