2009-10-30 67 views
7

我有我使用的是DataTemplate内的用户控件,这UserControl包含被绑定我UserControl价值财产(声明为DependencyProperty)一个TextBox。在数据模板中,我将这个属性与我的实际属性说名称(也是DependencyProperty)。它正常工作,我分配一个值来名称的特性,同时加载和我TextBox显示它,我改变从TextBox的价值,同时也更新我的名称属性。 现在,当我在依赖项属性中添加PropertyChangedEventHandler时,问题出现了,我检查该值是否有效,如果有效,则不执行任何操作,如果无效,则执行任何操作。在价值无效的情况下,当我将其分配给旧值时,属性更新但它不显示更新值在我的TextBoxUserControl中。谁能告诉我为什么?WPF:文本框的文本没有更新

XAML的UserControl

<UserControl x:Name="usercontrol"> 
    <StackPanel> 
     <TextBlock ......./> 
     <TextBox Binding={Binding ElementName=usercontrol, Path=Value, Mode=TwoWay}/> 
    </StackPanel> 
</UserControl> 

在后面代码是DependencyProperty

我在我的DataTemplate使用此:

<HierarchicalDataTemplate DataType="{x:Type myLib:myClass}" ItemsSource="{Binding Children}"> 
    <Expander Header="{Binding}"> 
     <WrapPanel> 
      <edproperty:TextPropertyEditor Caption="Name" Value="{Binding Name, Mode=TwoWay}"/> 
      <edproperty:TextPropertyEditor .................../> 
      <edproperty:TextPropertyEditor .................../> 
      <edproperty:TextPropertyEditor ...................../> 
     </WrapPanel> 
    </Expander> 
</HierarchicalDataTemplate> 

此模板我在中使用。里面TreeView我进入这将更新我UserControl价值属性TextBox值,这反过来又更新名称的myClass我分配财产PropertyChangedCallback名称属性,myClass,执行一些验证和重新分配OldValue如果验证失败。它反过来更新价值财产也,但我仍然看到TextBox具有相同的价值,我刚才进入而不是更新的一个。

​​
+2

没有看到您的代码,这将是一个难以适当评论。你可以发布你的代码吗? – 2009-10-30 10:54:48

+0

它太多了,不能发布。你可以问你是否想要更多的解释。 – viky 2009-10-30 13:27:59

+2

不,你可以写最小的代码片来重现......否则,我们会猜测,而不是回答。没有人喜欢不确定性。特别是程序员.. – Anvaka 2009-10-30 14:49:42

回答

0

它看起来像你破坏了绑定时你直接从代码中设置属性值的后面。

您不应该那样修改属性。使用value coercion mechanism并验证Coerce值回调中的输入。

+0

我用这种方式也是同样的问题,我的文本框的值不会更新。 – viky 2009-10-30 13:26:55

+0

我已经更新了我的问题,你能告诉我什么吗? 对不起延迟 – viky 2009-11-10 12:52:29

0

阿努拉格,

有很多假设,我要在这里做的,但我给它一个镜头。

你可能有这样的事情......

// ... 
public static string GetValue(Dependency obj) 
{ 
    // ... 
} 

// ... 
public static void SetValue(DependencyObject obj, string value) 
{ 
    // ... 
} 

// Using a DependencyProperty as the backing store for Value. This enables animation, styling, binding, etc... 
public static readonly DependencyProperty ValueProperty = 
    DependencyProperty.RegisterAttached("Value", typeof(string), typeof(MyCustomControl), new UIPropertyMetadata(OnValuePropertyChanged)); 

public static void OnValuePropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) 
{ 
    string newValue = e.NewValue as string; 

    // You validate your value here, 
    // Then if fails, revert to old value. 
    if(!SomeCondtion(newValue)) SetValue(obj,e.OldValue as string); 

} 

这绝对不是验证数据的最佳方式。还有其他更有效的方法可以给你更多的灵活性。

  1. 在您的TexBox上应用ValidationRule。这是我的第一个建议,因为它可以让你控制验证失败时显示错误。如果您经过简单验证,请查看我的article
  2. 侦听TextBox.TextChanged事件。这很麻烦,而且在大多数黑客中都不能重复使用。
  3. 请勿使用DependecyPropertyChanged回调方法。使用已注册的字符串属性并在您的设置器中应用逻辑,例如

    public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(string), typeof(UserControlWithTextBox)); 
    
    
    private string _oldValue; 
    public string Value 
    { 
        get { return GetValue(ValueProperty) as string; } 
        set 
        { 
         // Check if the value passes your validation logic 
         if(SomeCondtion(value)) 
         { 
          // If yes, then set the value, and record down the old value. 
          SetValue(ValueProperty, value); 
          _oldValue = value; 
         } 
         else 
         { 
          // Else logic fails, set the value to old value. 
          SetValue(ValueProperty, _oldValue); 
         } 
         // Implement INotifyPropertyChanged to update the TextBox. 
         if(PropertyChanged != null) 
          PropertyChanged(this, new PropertyChangedEventArgs("Value")); 
        } 
    } 
    

再次,你可以从我的回答看,你仍然可以显示你的问题代码,以帮助别人回答你的问题,无论您的解决方案可能多么复杂(如果你想有一个很好的答案,你需要努力提出一个好问题)。我的答案可能不适合你,但也许它可能会给你一些“谷歌搜索”的方向。希望能帮助到你。

+0

我已经更新了我的问题,对不起延迟 为什么它发生在我的文本框? – viky 2009-11-10 12:53:30

+0

当WPF通过绑定或setter或通过其他此类机制更新属性时,不会在您的示例中添加到setter的验证。建议在使用依赖项属性时不要在访问器或增变器中放置任何东西。 – jpierson 2010-12-07 22:37:52

1

我知道这个问题是关于文本框但RichTextBox中你可以使用UpdateLayout请()。

rtb.AppendText("Text"); 
rtb.ScrollToEnd(); 
rtb.UpdateLayout();