2009-10-30 15 views
7

Tôi có một điều khiển người dùng mà tôi đang sử dụng bên trong một DataTemplate, UserControl này chứa một TextBox được binded với Value tài sản (khai báo là một DependencyProperty) của UserControl tôi. Trong mẫu dữ liệu, tôi ràng buộc thuộc tính Giá trị với thuộc tính thực tế của tôi là Tên (cũng là DependencyProperty). Nó hoạt động đúng cách, tôi chỉ định giá trị cho Tên thuộc tính trong khi đang tải và hiển thị số TextBox, tôi thay đổi giá trị từ TextBox và nó cập nhật tài sản của tôi Tên. Bây giờ vấn đề xảy ra khi tôi thêm một PropertyChangedEventHandler vào thuộc tính phụ thuộc, tôi kiểm tra giá trị nếu nó hợp lệ, không làm gì nếu hợp lệ và gán giá trị cũ nếu không hợp lệ. Trong trường hợp giá trị không hợp lệ, khi tôi chỉ định giá trị cũ, cập nhật thuộc tính nhưng giá trị đó không hiển thị giá trị được cập nhật trong số TextBox của UserControl. bất cứ ai đó có thể trả lời tôi tại sao?WPF: TextBox Văn bản được không cập nhật

XAML của tôi UserControl:

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

Trong mã đằng sau Value là một DependencyProperty

Tôi đang sử dụng này trong tôi 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> 

mẫu này tôi sử dụng trong một TreeView. Bên TreeView tôi nhập giá trị trong TextBox mà cập nhật Value tài sản của UserControl của tôi, rằng trong bản cập nhật lần lượt Tên tài sản của myClass Tôi gán một PropertyChangedCallback-Tên tôi về tài sản trong myClass, thực hiện một số xác nhận và giao lại các OldValue nếu xác thực không thành công. Nó lần lượt cập nhật Giá trị tài sản cũng có, nhưng tôi vẫn thấy rằng TextBox có cùng giá trị mà tôi đã nhập trước đó không phải là cập nhật.

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 
    } 
+2

Nếu không nhìn thấy mã của bạn, đây sẽ là một khó khăn để bình luận đúng cách. Bạn có thể đăng mã của bạn được không? –

+0

quá nhiều, không thể đăng. Bạn có thể hỏi xem bạn có muốn giải thích thêm không. – viky

+2

Không, bạn có thể viết đoạn mã tối thiểu để tái tạo ... Nếu không, chúng tôi sẽ đoán, không trả lời. Không ai thích sự không chắc chắn. Đặc biệt là lập trình viên .. – Anvaka

Trả lời

7

Sau nhiều ngày tìm kiếm xung quanh và rất nhiều tìm kiếm tôi tìm thấy các giải pháp của vấn đề của tôi

Sau khi tất cả xác nhận thực hiện và gán giá trị cũ và cập nhật các tài sản dependecy, tôi cần phải Cal phương pháp UpdateTarget(), để cập nhật giá trị trong TextBox của tôi.

Đây là những gì giải thích những giải pháp tốt hơn

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

+0

Cảm ơn bạn! Bạn đã cứu cuộc đời tôi!! –

0

Dường như bạn đang phá vỡ ràng buộc khi bạn đặt giá trị thuộc tính trực tiếp từ mã phía sau.

Bạn không nên sửa đổi thuộc tính theo cách đó. Sử dụng value coercion mechanism và xác thực đầu vào trong gọi lại giá trị Coerce.

+0

tôi cũng sử dụng cách này nhưng vẫn còn cùng một vấn đề, giá trị của hộp văn bản của tôi không cập nhật. – viky

+0

i hav đã cập nhật câu hỏi của tôi, bạn có thể đề xuất cho tôi bất kỳ điều gì không? xin lỗi vì sự chậm trễ – viky

0

Anurag,

Có rất nhiều giả định tôi phải thực hiện ở đây, nhưng tôi sẽ thực hiện.

Bạn có thể có một cái gì đó như thế này ...

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

} 

này chắc chắn không phải là phương pháp tốt nhất để xác nhận dữ liệu. Có những cách tiếp cận khác hiệu quả hơn sẽ giúp bạn linh hoạt hơn.

  1. Áp dụng ValidationRule trên TexBox của bạn.Đây là khuyến nghị đầu tiên của tôi vì nó sẽ cho bạn quyền kiểm soát hiển thị lỗi khi xác thực không thành công. Nếu bạn sau khi xác thực đơn giản, hãy xem article của tôi.
  2. Nghe sự kiện TextBox.TextChanged. Điều này là cồng kềnh và không thể sử dụng lại nhiều nhất là bị tấn công.
  3. Không sử dụng phương thức gọi lại DependecyPropertyChanged. Sử dụng thuộc tính chuỗi đã đăng ký và trong setter của bạn, áp dụng logic, ví dụ:

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

Một lần nữa, như bạn có thể nhìn thấy từ câu trả lời của tôi rằng bạn vẫn có thể hiển thị mã trong câu hỏi của bạn để giúp đỡ người khác trả lời câu hỏi của bạn không có vấn đề như thế nào phức tạp giải pháp của bạn có thể (nếu bạn muốn có một câu trả lời tốt , bạn cần phải nỗ lực để đặt một câu hỏi hay). Câu trả lời của tôi có thể không phù hợp với bạn nhưng có lẽ nó có thể cung cấp cho bạn một số chỉ dẫn "Googling". Hy vọng nó giúp.

+0

i hav đã cập nhật câu hỏi của tôi, xin lỗi vì sự chậm trễ tại sao nó xảy ra với hộp văn bản của tôi? – viky

+0

Xác nhận hợp lệ được thêm vào bộ đặt trong ví dụ của bạn sẽ không xảy ra khi WPF cập nhật thuộc tính thông qua ràng buộc hoặc thiết lập hoặc thông qua các cơ chế khác. Bạn không nên đặt bất kỳ thứ gì trong trình truy cập hoặc trình tắt của bạn khi sử dụng các thuộc tính phụ thuộc. – jpierson

1

Tôi biết câu hỏi này là về TextBox nhưng đối với RichTextBox bạn sẽ sử dụng UpdateLayout().

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