如何在UserControl中实现更新LostFocus源代码的DependencyProperty?

如何在UserControl中实现更新LostFocus源代码的DependencyProperty?

问题描述:

我正在实施名为PhoneBox的UserControl,其中包含一个TextBox,一些自定义逻辑,并且有一个名为PhoneNo的DependencyProperty。它将用于双向绑定场景,LostFocusUpdateSourceTrigger。所以我写了下面的代码 -如何在UserControl中实现更新LostFocus源代码的DependencyProperty?

XAML(用户控件):

<StackPanel> 
    <TextBox Name="txtPhone" MinWidth="120" MinHeight="23" LostFocus="txtPhone_LostFocus" GotFocus="txtPhone_GotFocus"/> 
</StackPanel> 

代码隐藏(用户控件):

public partial class PhoneBox : UserControl 
{ 
    //Some Code 

    static PhoneBox() 
    { 
     FrameworkPropertyMetadata phoneNoMetadata = 
      new FrameworkPropertyMetadata(new PropertyChangedCallback(OnPhoneNoChanged), 
              new CoerceValueCallback(CoercePhoneNoValue)); 
     PhoneNoProperty = DependencyProperty.Register("PhoneNo", typeof (string), typeof (PhoneBox), 
                 phoneNoMetadata, 
                 new ValidateValueCallback(ValidatePhoneNoValue)); 
    } 

    public readonly static DependencyProperty PhoneNoProperty; 
    public string PhoneNo 
    { 
     get { return (string)GetValue(PhoneNoProperty); } 
     set { SetValue(PhoneNoProperty, value); } 
    } 

    private static void OnPhoneNoChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     PhoneBox phoneBox = (PhoneBox)d; 
     string newValue = (string)e.NewValue; 

     phoneBox.txtPhone.Text = newValue; 
    } 

    private static object CoercePhoneNoValue(DependencyObject d, object basevalue) 
    { 
     return basevalue; 
    } 

    private static bool ValidatePhoneNoValue(object value) 
    { 
     return true; 
    } 

    private void txtPhone_LostFocus(object sender, RoutedEventArgs e) 
    { 
     this.SetValue(PhoneNoProperty, this.txtPhone.Text); 
    } 

    private void txtPhone_GotFocus(object sender, RoutedEventArgs e) 
    { 
     if (!String.IsNullOrEmpty(txtPhone.Text)) 
      this.txtPhone.Text = this.FilterText(txtPhone.Text); 
    } 

    private string FilterText(string text) 
    { 
     //Some cutom logic 
    } 

    //Some more Code 
} 

XAML(消费者):

<pbc:PhoneBox PhoneNo="{Binding Path=User.Phone, Mode=TwoWay, UpdateSourceTrigger=LostFocus}"/> 

它作品。但我的问题是,我使用txtPhone_LostFocus事件处理程序来设置proerty值(反过来更新源)的方式是否恰当?有没有更适当的方法来做到这一点?我是这个DependencyProperty的新手,所以任何指导,建议和意见将非常感谢。

+0

你一定要明白引发LostFocus是文本框的默认?我做的是 – 2012-07-19 07:57:10

+0

。这里的重点不是特定于“TextBox”。 – atiyar 2012-07-19 08:01:13

+0

关于绑定语法:Mode = TwoWay是TextBox.Text的默认设置,你可以没有。 RelativeSource虽然很复杂,但是可以到这里。您甚至可以为您的程序集声明一个XAML名称空间,并使用UserControls精确类型,如{x:Type my:PhoneBox},以便更具体。通常情况下,我会使用ElementName绑定语法,但是随后您需要为UserControl提供一个x:Name属性,并且如果您在其自己的XAML中设置了该属性,并且然后使用UserControl的客户端XAML尝试设置x:Name在外面。 – hbarck 2012-08-28 17:44:16

的WPF的方式来处理这种情况是有之间的用户控件的DependencyProperty和绑定在UserControl的XAML文件中声明的TextBox。这也是你设置LostFocus UpdateSourceTrigger(你不需要,因为它是默认行为)。您将在TextBox(即UserControl内)声明Binding,因此使用UserControl的客户端代码可以*设置PhoneNo属性(来自UserControl外部)的另一个绑定。另外,如果您的CoerceValue回调只返回基值,那么最好不要从头开始。

这可能是什么意思大卫最初...

在这种情况下,我宁愿在DP元数据中使用UpdateSourceTrigger枚举,而不使用所有冗余方法:让WPF为您做这些事情总是更好:如果可以的话他们会做得更好,更快。

另外在这种情况下,我个人发现在元数据中读取比在lostFocus方法中读取要容易得多。但这是我猜想的味道问题。

编辑:不,不,我明白你的意思,但我的答案可能并不清楚自己。这大致就是我会做(只是给你一个提示,这将需要在你的情况下,一些调谐):

public partial class PhoneBox : UserControl 
{ 
    public static readonly DependencyProperty PhoneNoProperty = DependencyProperty.Register(
     "PhoneNo", 
     typeof (string), 
     typeof (PhoneBox), 
     new UIPropertyMetadata(UpdateSourceTrigger.LostFocus), 
     new ValidateValueCallback(ValidatePhoneNoValue)); 

    public string PhoneNo 
    { 
     get { return (string)GetValue(PhoneNoProperty); } 
     set { SetValue(PhoneNoProperty, value); } 
    } 

// ... your code here. 

} 
+0

以及ACTUALLY保存文本的'TextBox'究竟会受到这个影响?我将如何获取和设置文本?这不会导致'TextBox'失去焦点。你有没有在真实应用程序代码中尝试它? – atiyar 2012-07-19 17:20:27

+0

它实际上取决于您的usercontrol的结构以及您计划如何使用它。假设在你的用户控件中有更多的子控件,并且当焦点从文本框转到其他子控件时,你想更新属性,在这种情况下,是的,你被锁定在LostFocus事件选项,因为usercontrol本身会即使文本框不再存在,仍然保持专注。但是如果你只是像你写的文本框一样,你不能处于userControl所关注的位置,但textBox不是,你可以使用第二个选项。 – David 2012-07-20 07:09:46

+0

“...如果你只是有你写的文本框,你不能在userControl的位置,但文本框不是” - 你真的有一些逻辑,现在可以看到。但情况是,无论我通过MetaData构造函数提供'UpdateSourceTrigger'还是通过XAML''PhoneNo'都不会在'LostFocus'上更新。我已经发布了整个代码,你可以自己测试一下。 'PhoneNo'在'LostFocus'上更新的唯一情况是当我通过'txtPhone_LostFocus'事件处理程序使用'SetValue()'时。 – atiyar 2012-07-20 07:57:18