【问题标题】:WPF: TextBox Text is not updatingWPF:文本框文本未更新
【发布时间】:2009-10-30 09:26:40
【问题描述】:

我有一个在DataTemplate 中使用的用户控件,这个UserControl 包含一个TextBox,它与我的Value 属性(声明为DependencyProperty)绑定UserControl。在数据模板中,我将此 Value 属性与我的实际属性绑定,例如 Name(也是 DependencyProperty)。它工作正常,我在加载时为 Name 属性分配了一个值,我的 TextBox 显示它,我从 TextBox 更改值,它也更新了我的 Name 属性. 现在问题来了,当我在依赖属性中添加 PropertyChangedEventHandler 时,我检查该值是否有效,如果有效则不执行任何操作,如果无效则分配旧值。如果值无效,当我为其分配旧值时,属性会更新,但它不会在我的TextBox 或UserControl 中显示更新的值。谁能告诉我为什么?

XAML 我的UserControl:

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

在Value后面的代码中是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 中使用的这个模板。在TreeView 中,我在TextBox 中输入值,它更新了我的UserControl 的Value 属性,进而更新了myClass 我正在分配的Name 属性一个PropertyChangedCallback 到myClass 中我的Name 属性,执行一些验证并在验证失败时重新分配OldValue。它反过来也会更新 Value 属性,但我仍然看到 TextBox 具有与我之前输入的值相同的值,而不是更新后的值。

public string Name
    {
        get
        {
            return (string)GetValue(NameProperty);
        }
        set
        {
            SetValue(NameProperty, value);
        }
    }

    // Using a DependencyProperty as the backing store for Name.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty NameProperty =
        DependencyProperty.Register("Name", typeof(string), typeof(myClass), new UIPropertyMetadata(null, OnNameChanged));

    protected static void OnNameChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
    {
        if(checkRequired && !IsValid(e.NewValue.ToString()))
        {
            checkRequired=false;
            (sender as myClass).Name = args.OldValue.ToString();
        }
    }

    private static bool IsValid(string name)
    {
         .............some logic here
    }

【问题讨论】:

  • 没有看到您的代码,这将是一个很难正确评论的问题。你能把你的代码贴出来吗?
  • 太多了,发不出去。您可以询问是否需要更多解释。
  • 不,你可以编写最少的代码片段来重现......否则,我们将猜测,而不是回答。没有人喜欢不确定性。尤其是程序员..

标签: wpf xaml textbox user-controls datatemplate


【解决方案1】:

经过几天的环顾和大量搜索,我找到了问题的解决方案

在完成所有验证并分配旧值和更新依赖属性之后,我需要调用 UpdateTarget() 方法来更新我的 TextBox 中的值。

这就是更好地解释解决方案的原因

http://social.msdn.microsoft.com/forums/en-US/wpf/thread/c404360c-8e31-4a85-9762-0324ed8812ef/

【讨论】:

  • 谢谢!你救了我的命!!
【解决方案2】:

我知道这个问题是关于 TextBox,但对于 RichTextBox,您会使用 UpdateLayout()。

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

【讨论】:

    【解决方案3】:

    当您直接从后面的代码设置属性值时,您似乎正在破坏绑定。

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

    【讨论】:

    • 我也用过这种方式,但还是同样的问题,我的文本框的值没有更新。
    • 我已经更新了我的问题,你能建议我什么吗?抱歉耽搁了
    【解决方案4】:

    阿努拉格,

    我必须在这里做出很多假设,但我会试一试。

    你可能有这样的东西......

    // ...
    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"));
          }
      }
      

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

    【讨论】:

    • 我已经更新了我的问题,抱歉耽搁了,为什么我的文本框会发生这种情况?
    • 当 WPF 通过绑定或 setter 或通过其他此类机制更新属性时,不会发生在示例中添加到 setter 的验证。建议不要在使用依赖属性时在访问器或修改器中添加任何内容。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-27
    • 1970-01-01
    相关资源
    最近更新 更多