首页 > 其他分享 >WPF依赖附加属性

WPF依赖附加属性

时间:2023-11-22 10:45:45浏览次数:40  
标签:obj int 附加 static DependencyObject WPF public 属性

依赖附加属性的定义

可使用代码片段-propa快速生成,输入propa后按两次Tab键

        public static int GetMyProperty(DependencyObject obj)
        {
            return (int)obj.GetValue(MyPropertyProperty);
        }

        public static void SetMyProperty(DependencyObject obj, int value)
        {
            obj.SetValue(MyPropertyProperty, value);
        }

        // Using a DependencyProperty as the backing store for MyProperty.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty MyPropertyProperty =
            DependencyProperty.RegisterAttached("MyProperty", typeof(int), typeof(ownerclass), new PropertyMetadata(0));

属性名称MyProperty,方法名默认为GetMyProperty和SetMyProperty不要随意更改。

DependencyProperty.RegisterAttached的参数与依赖属性一致。

依赖属性所在的类必须继承DependencyObject,而依赖附加属性所在的类不需要。

依赖属性必须在依赖对象,而依赖附加属性不一定,关注的是被附加的对象是否是依赖对象。

在普通类中定义依赖属性,GetValue与SetValue报错,因为这两个方法定义在DependencyObject中。

在普通类中可以定义依赖附加属性。

依赖附加属性的意义与作用

给其他对象提供依赖属性功能

    public class ZxPanel : Panel
    {
        // 依赖附加属性的方法封装
        public static int GetIndex(DependencyObject obj)
        {
            return (int)obj.GetValue(IndexProperty);
        }

        public static void SetIndex(DependencyObject obj, int value)
        {
            obj.SetValue(IndexProperty, value);
        }

        // 依赖附加属性的 声明与注册
        public static readonly DependencyProperty IndexProperty =
            DependencyProperty.RegisterAttached("Index", typeof(int), typeof(ZxPanel), new PropertyMetadata(-1));
    }

在ZxPanel类中定义一个依赖附加属性Index。

<Border Background="Orange" Height="50" local:ZxPanel.Index="3"/>

在Xaml中为Border添加依赖附加属性。

有些对象中不能做绑定的功能

PasswordBox控件的Password属性不具备绑定功能。

public class PWHelper
    {
        public static string GetPassword(DependencyObject obj)
        {
            return (string)obj.GetValue(PasswordProperty);
        }

        public static void SetPassword(DependencyObject obj, string value)
        {
            obj.SetValue(PasswordProperty, value);
        }
        public static readonly DependencyProperty PasswordProperty =
            DependencyProperty.RegisterAttached("Password", typeof(string), typeof(PWHelper), new PropertyMetadata(""
                , new PropertyChangedCallback(OnPasswordChanged)));
        
        /// <summary>
        /// 
        /// </summary>
        /// <param name="dependencyObject">实附加的对象</param>
        /// <param name="e"></param>
        private static void OnPasswordChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            //var control = (d as PasswordBox);
            //if (control == null) return;

            if (d is PasswordBox control)
            {
                control.Password = e.NewValue.ToString();
            }
        }
    }

在PWHelper类中定义一个依赖附加属性Password,并添加值变化回调,将新值赋值给PasswordBox控件的Password属性。

public static object GetAttached(DependencyObject obj)
        {
            return (object)obj.GetValue(AttachedProperty);
        }

        public static void SetAttached(DependencyObject obj, object value)
        {
            obj.SetValue(AttachedProperty, value);
        }
        public static readonly DependencyProperty AttachedProperty =
            DependencyProperty.RegisterAttached("Attached", typeof(object),
                typeof(PWHelper), new PropertyMetadata(null, new PropertyChangedCallback(OnAttachedChanged)));

        private static void OnAttachedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var control = (d as PasswordBox);
            if (control == null) return;

            // 
            control.PasswordChanged -= Control_PasswordChanged;
            control.PasswordChanged += Control_PasswordChanged;
        }
        
        
        private static void Control_PasswordChanged(object sender, RoutedEventArgs e)
        {
            SetPassword((DependencyObject)sender, (sender as PasswordBox).Password);
        }

再定义一个依赖附加属性Attached,并添加值回调,用来挂载事件。

依赖附加属性可以使用绑定。

布局控件做动态子项

    public class ZxPanel : Panel
    {
        // 依赖附加属性的方法封装
        public static int GetIndex(DependencyObject obj)
        {
            return (int)obj.GetValue(IndexProperty);
        }

        public static void SetIndex(DependencyObject obj, int value)
        {
            obj.SetValue(IndexProperty, value);
        }

        // 依赖附加属性的 声明与注册
        public static readonly DependencyProperty IndexProperty =
            DependencyProperty.RegisterAttached("Index", typeof(int), typeof(ZxPanel), new PropertyMetadata(-1));
    }

在继承Panel类的ZxPanel类中定义依赖附加属性Index。

        <local:ZxPanel ColumnSpace="10" RowSpace="10" Test="123">
            <Border Background="Orange" Height="50" local:ZxPanel.Index="3"/>
            <Border Background="Green" Height="50"/>
            <Border Background="Blue" Height="50"/>
            <Border Background="Red" Height="50"/>

            <local:DependencyPropertyStudy local:ZxPanel.Index="2" Height="50" Background="Gray"
                                           x:Name="dps"/>
        </local:ZxPanel>

在ZxPanel控件下的子项可以使用local:ZxPanel.Index="3"。

protected override Size MeasureOverride(Size availableSize)
        {
            double total_y = 0;

            double per_width = (availableSize.Width - ColumnSpace * 2) / 3;

            foreach (UIElement item in this.InternalChildren)
            {
                item.Measure(new Size(per_width, double.MaxValue));
                total_y += item.DesiredSize.Height + RowSpace;
            }
            return new Size(availableSize.Width, total_y);
        }

        // 排列
        protected override Size ArrangeOverride(Size finalSize)
        {
            double offset_y = 0, offset_x = 0;
            double per_width = (finalSize.Width - ColumnSpace * 2) / 3;
            double maxHeight = 0;

            List<FrameworkElement> elements = new List<FrameworkElement>();
            for (int i = 0; i < this.InternalChildren.Count; i++)
            {
                elements.Add((FrameworkElement)this.InternalChildren[i]);
            }

            for (int i = 1; i < this.InternalChildren.Count + 1; i++)
            {
                UIElement item = elements.FirstOrDefault(e => GetIndex(e) == i);
                if (item == null)
                {
                    // 这个是容器中的子控件(DependencyPropertyStudy)
                    item = this.InternalChildren[i - 1];
                }
                //var index = GetIndex(item);// 获取对应对象的Index附加属性值

                item.Arrange(new Rect(offset_x, offset_y, per_width, item.DesiredSize.Height));
                maxHeight = Math.Max(maxHeight, item.DesiredSize.Height);

                if (i % 3 == 0)
                {
                    offset_y += maxHeight + RowSpace;
                    offset_x = 0;
                    maxHeight = 0;
                }
                else
                    offset_x += per_width + ColumnSpace;


            }
            return base.ArrangeOverride(finalSize);
        }

在ZxPanel类中重写MeasureOverride与ArrangeOverride方法,重新定义控件的测量与排序方法。安装子控件的Index属性重新进行排序。

此用法与<Grid的属性<Grid.Column>和<Grid.Row>类似。

<Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <local:DependencyPropertyStudy Tag="123" Command="{Binding}" CP="{Binding}"
                                       DPS="{Binding Value}" Grid.Column="1"/>
    </Grid>

Grid.Column="1"用于辅助布局控件

标签:obj,int,附加,static,DependencyObject,WPF,public,属性
From: https://www.cnblogs.com/ZHIZRL/p/17848436.html

相关文章

  • WPF --- 如何以Binding方式隐藏DataGrid列
    引言如题,如何以Binding的方式动态隐藏DataGrid列?预想方案像这样:先在ViewModel创建数据源People和控制列隐藏的IsVisibility,这里直接以MainWindow为DataContextpublicpartialclassMainWindow:Window,INotifyPropertyChanged{publicMainWindow(){......
  • white-space属性
    white-space属性表csswhite-space这个css样式,用来设置element元素对内容中的空格的处理方式,有着几个可选值:normal,nowrap,pre,pre-wrap,pre-line没有设置white-space属性,则默认为white-space:normal。normal表示合并空格,多个相邻空格合并成一个空格,在源码中的换行作为空格处理......
  • 有趣的Java之@Autowired属性注入问题
    ......
  • C# 动态类添加属性
    1.定义JsonDataObject publicsealedclassJsonDataObject:DynamicObject{privatereadonlyDictionary<string,object>_properties;publicJsonDataObject(Dictionary<string,object>properties){_properties=properties;......
  • 三种办法遍历对象数组,获取数组对象中所有的属性值(key,value);四种方法查找对象数组里面
    一,获取对象数组中某属性的所有值如果是要获取具体第几个属性的值,倒是可以用arr[i].name的方法来实现。若是全部的属性的值,并返回一个新的数组嘞,思路是加循环遍历方法如下。1、from方法vararr=[{id:1,name:"小明"},{id:2......
  • Spring5学习随笔-事务属性详解(@Transactional)
    学习视频:【孙哥说Spring5:从设计模式到基本应用到应用级底层分析,一次深入浅出的Spring全探索。学不会Spring?只因你未遇见孙哥】第三章、Spring的事务处理1.什么是事务?事务是保证业务操作完整性的一种数据库机制事务的4特点:ACIDA原子性C一致性I隔离性D持久性2.如何......
  • 界面控件DevExpress WPF流程图组件,完美复制Visio UI!(一)
    DevExpressWPFDiagram(流程图)控件帮助用户完美复制MicrosoftVisioUI,并将信息丰富且组织良好的图表、流程图和组织图轻松合并到您的下一个WPF项目中。P.S:DevExpressWPF拥有120+个控件和库,将帮助您交付满足甚至超出企业需求的高性能业务应用程序。通过DevExpressWPF能创建有着......
  • 微信小程序 布局对齐属性
    1、效果展示2、代码展示<!-- 引用模板 import --><view class="content" ><view class="content-item" style="background: skyblue" > 1</view><view class="content-item" style="background: #ff0000" >......
  • wpf 自定义按钮模板
    <ButtonWidth="300"Height="100"Content="自定义按钮"Background="Bisque"FontSize="23"Foreground="Orchid"><Button.Template><ControlTemplateTargetType=&qu......
  • wpf 任意控件绑定Command
    <BorderBackground="White" BorderBrush="Gray" BorderThickness="1" CornerRadius="2"> <Border.InputBindings> <MouseBindingCommand="{BindingDataContext.BorderCommand,RelativeSource={RelativeS......