【问题标题】:Why is my Dependency Property written with the propdp snippet not working?为什么我用 propdp 代码段编写的依赖属性不起作用?
【发布时间】:2014-08-26 18:41:16
【问题描述】:

我有一个具有简单依赖属性的类,它是在 Visual Studio 中的 propdp sn-p 的帮助下编写的。我从TextBox 派生了这个类,并给了它一个我想成为依赖属性的PrePend 属性。我想要这样,如果用户将PrePend 设置为“Hello”并将Text 设置为“World”,Text getter 将返回“Hello World”。我的问题是代码似乎忽略了我的 PrePend 依赖属性。

我的课在这里:

internal class MyTextBox : TextBox
{
    public new string Text
    {
        get { return this.PrePend + base.Text; }
        set { base.Text = value; }
    }

    public string PrePend
    {
        get { return (string)GetValue(PrePendProperty); }
        set { SetValue(PrePendProperty, value); }
    }

    // Using a DependencyProperty as the backing store for PrePend.  
    //   This enables animation, styling, binding, etc...
    public static readonly DependencyProperty PrePendProperty =
        DependencyProperty.Register("PrePend", typeof(string), 
          typeof(MyTextBox), new PropertyMetadata(""));
}

我通过使用propdp sn-p 获得了此代码。我只添加了Text setter。

我的XAML 代码是这样的:

<local:MyTextBox PrePend="Hello " Text="World" />

当我运行代码时,屏幕显示“世界”。我在Text getter 和setter 以及PrePend getter 和setter 中设置了断点,但代码永远不会在那里中断。

这个简单的例子我做错了什么?我不应该使用propdp 代码 sn-p 来执行此操作吗?我不太了解依赖属性。

【问题讨论】:

  • 触发 PropertyChanged 事件?
  • 我不确定覆盖您的 Text 值是否安全。 Text 中的 TextBox 也是一个依赖属性。在不更改属性的情况下重新实现它听起来不是一个好主意。
  • 我应该把 PropertyChanged 事件放在哪里?在文本设置器中?我对 base.Text setter 的调用不会触发该事件吗?还是 PrePend 设置器?在这种情况下,对 SetValue 的调用不会触发该事件吗?除此之外,如果需要,propdp sn-p 不会包含对 PropertyChanged 的​​调用吗?

标签: c# wpf dependency-properties


【解决方案1】:

由于数据绑定/动画更新而更改值时,WPF 不使用 setter。

如果你想响应依赖属性的变化,你可以做以下两件事之一:

  1. 在注册调用中向 PropertyMetaData 添加一个 PropertyChanged 处理程序。

  2. 不要在控件中处理更改,而是在 ViewModel 中处理它。

【讨论】:

  • 我最终选择了您的第一个选项。谢谢。我觉得有趣的是 Visual Studio 附带的 propdp sn-p 似乎不起作用。也许我理解错了。我必须创建自己的包含 PropertyChanged 处理程序的 sn-p,因为我永远无法记住该样板代码。
  • 他们只是没有在 sn-p 中添加处理程序。通常,大多数依赖属性不会处理此事件。请注意,如果实施不当并且属性经常更改,它可能会降低您的应用速度
【解决方案2】:

这是“非法的”,因为 WPF 总是直接访问 DependencyProperties,该属性只不过是一个包装器。这就是为什么您应该永远不要更改或将逻辑放入属性中,wpf 将永远不会在内部使用它们!

public new string Text // Bad pie!
{
    get { return this.PrePend + base.Text; } // Bad pie!
    set { base.Text = value; }
}

如果您想在属性更改时执行某些操作,请在声明依赖项属性时添加 OnPrePendPropertyChanged 处理程序。

IE:

public static readonly DependencyProperty PrePendProperty = DependencyProperty.Register("PrePend", typeof(string), typeof(MyTextBox), new PropertyMetadata(String.Empty, OnPrePendPropertyChanged ));

private static void OnPrePendPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
{
   var ctl = sender as MyTextBox ;
   ctl.OnPrePendChanged();
}

protected virtual void OnPrePendChanged()
{
   // do your magic here
}

您还可以将处理程序添加到现有的依赖属性,例如您的文本属性。这必须在类的静态构造函数中完成。 This is described in this post.

static MyTextBox 
{
    DefaultStyleKeyProperty.OverrideMetadata(typeof(MyTextBox), new FrameworkPropertyMetadata(typeof(MyTextBox)));
    TextBox.TextProperty.OverrideMetadata(typeof(MyTextBox), new FrameworkPropertyMetadata(new PropertyChangedCallback(OnTextPropertyChanged)));
}

// Add your handlers as above

如果可能,我个人宁愿为 I.E 创建一个 Behavior。扩展控件的功能。

在目前的情况下(我怀疑你正在试验?),我会考虑使用 std TextBox,然后将 Text 属性绑定到 vm 上的一个 prop 并在那里发挥你的作用,和/或在绑定中使用IValueConverter

希望对你有帮助

干杯,

斯蒂安

【讨论】:

  • 我删除了我的 Text setter,将我的 XAML 更改为 &lt;local:MyTextBox PrePend="Hello " /&gt; 并更改了我的 Prepend setter,以便它调用 SetValue(TextProperty, value);。这样,我希望出现 PrePend 值“Hello”。相反,我什么也得不到。即使我通过Setvalue(...) 设置文本,也永远不会设置文本。当我在 PrePend 设置器中设置断点并运行程序时,断点永远不会触发:我的 PrePend 设置器根本没有被调用。我认为这里有其他问题。
  • @user2023861 除非您更改文本框的控件模板以显示 PrePend 属性而不是 Text 属性,否则这将不起作用。 Mate 在您的视图模型中执行此操作或使用行为代替! :) 行为非常简单和漂亮。
猜你喜欢
  • 1970-01-01
  • 2016-05-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-19
相关资源
最近更新 更多