XAML依赖属性与常规属性

3
如果我有这个:
    public class BoardCalc : FrameworkElement
    {
        public BoardCalc()
        {
            this.Loaded += BoardCalc_Loaded;
        }

        void BoardCalc_Loaded(object sender, RoutedEventArgs e)
        {
            Boards = Math.Floor(LengthRequired / 16);
            BoardsRequired2 = Math.Floor(LengthRequired / 16);
        }

        public Double LengthRequired { get; set; }

        private Double _Boards;
        public Double Boards
        {
            get
            {
                return _Boards;
            }
            set
            {
                _Boards = value;
            }
        }


        //public Double Boards
        //{
        //    get { return (Double)GetValue(BoardsProperty); }
        //    set { SetValue(BoardsProperty, value); }
        //}

        //// Using a DependencyProperty as the backing store for Boards.  This enables animation, styling, binding, etc...
        //public static readonly DependencyProperty BoardsProperty =
        //    DependencyProperty.Register("Boards", typeof(Double), typeof(BoardCalc), null);

        public Double BoardsRequired2
        {
            get { return (Double)GetValue(BoardsRequired2Property); }
            set { SetValue(BoardsRequired2Property, value); }
        }

        // Using a DependencyProperty as the backing store for BoardsRequired2.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty BoardsRequired2Property =
            DependencyProperty.Register("BoardsRequired2", typeof(Double), typeof(BoardCalc), null);



    }

我这样做:

 <StackPanel xmlns:Boards="clr-namespace:BoardsUtil" >
             <Boards:BoardCalc x:Name="boardCalc1"
                LengthRequired="5280"  />

             <TextBlock Text="{Binding ElementName=boardCalc1, Path=Boards}" />

             <TextBlock Text="{Binding ElementName=boardCalc1, Path=BoardsRequired2}" />

         </StackPanel>

两个问题:

  1. 当我使用依赖属性时,在设计时,Boards的值将被计算为330。如果我使用普通属性,则在设计时为0. 在运行时,任何一个都可以正常工作。这是否是我们所期望的?如果是或者不是,能否有人解释一下为什么,并指导我如何解决它并检查我的其余代码是否实际工作。

  2. 对于LengthRequired,我应该使用依赖属性吗?如果您从XAML设置属性,则应该使用依赖属性吗?但是,如果您仅从XAML绑定到属性,则可以使用普通属性?这是我们看到的行为吗?这是否是我们所期望的?为什么,让我决定做什么。

2个回答

4
主要使用依赖属性的原因是允许底层子系统提供额外的UI/XAML/WPF功能,即:
1)绑定。 在这段代码中:
<Slider x:Name="slid1" Maximum="5280" Minimum="16" Value="250" />
<Boards:BoardCalc x:Name="boardCalc1"
            LengthRequired="{Binding ElementName=slid1,Path=Value"  />

LengthRequired必须是一个依赖属性。您可以像这样设置LengthRequired

LengthRequired = "5280"

而且你可以这样做

Text={Binding ElementName=boardCalc1, Path=LengthRequired} ...

但是你不能使用Binding扩展来设置LengthRequired属性。

2) 动画 3) 样式

同样的基本原理。为了让底层UI子系统从0到100或其他数值进行动画,或者让子系统获取样式、主题等,它必须是依赖属性。

1,2,3. 使用依赖属性的原因。 对于常规属性,可以使用INotify。


2
设计者将计算板的价值。
引用MSDN(依赖属性概述):
依赖属性的目的是提供一种根据其他输入值计算属性值的方法。
设计模式不是运行时模式,设计者使用依赖属性,因为它专门反映它们。设计师没有订阅INotifyPropertyChanged,也不像依赖属性那样与普通属性交互。
我会在LengthRequired上放置一个notify property change,但除非您正在创建自定义控件,否则使用Dependency property过度了。
如果您从XAML设置属性,则应该使用Dependency。
不,可以在XAML中绑定(设置)任何属性,因为它只是反射。绑定通过提供的路由(路径信息)从数据上下文中的项目反射出来。
“绑定”的行为与获取数据的行为是不同的,后者发生在“绑定”之后。但是,如果你仅仅从XAML中绑定到一个属性,你可以使用普通属性吗?是的,但在大多数情况下,最好使用INotifyPropertyChanged操作来帮助进行绑定和检索数据。”
使用这些基本规则:
  • 在控件上使用依赖属性,因为它们在设计模式下可被控件的消费者识别。否则用户需要找到属性并且不能在XAML中设置值;不像依赖属性。
  • 任何属性都可以被绑定,但是发生的更改可能不会被传达给它所绑定的任何东西……为了提供这个过程良好的数据,使用INotifyPropertyChanged操作。

事实上,添加INotifyPropertyChanged的实现确实会影响设计师。它现在具有与DependencyProperty相同的价值。 - Andyz Smith
你能进一步描述一下依赖属性在“设计模式下可识别”的含义吗?或者用户如何“找到”该属性?还是说“无法设置属性”? - Andyz Smith
@AndyzSmith,你的终极目标是什么?在设计时获得一个工作版本吗?设计师做它该做的事情,并且可以在屏幕上显示数据到一定程度。如果正在创建控件,则使用依赖属性,如果不是,则使用普通属性。 - ΩmegaMan
为什么要使用依赖属性?你可以从XAML设置常规属性。你可以从XAML绑定到常规属性。你可以通过快速的INotify使设计师使用常规属性。 - Andyz Smith
2
@AndyzSmith 依赖属性的主要原因是,它们是静态的,允许未初始化的控件表达属性。当设计人员在设计界面上放置控件时,可以更改诸如“宽度”、“高度”、“文本”之类的内容,因为这些属性被公开为依赖属性。控件具有非依赖属性,但不应向用户显示这些属性。否则,如果没有依赖属性,只能在代码后台中连接控件。因此,任何控件都应将公共面向属性公开为DP,以允许在XAML中进行连接。希望对你有所帮助。 - ΩmegaMan
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接