2012-01-10 51 views
11

Tôi đang tạo một cửa sổ WPF với nhiều hộp văn bản, khi người dùng nhấn nút OK, tôi muốn tất cả các hộp văn bản được đánh giá là không trống. Tôi hiểu rằng tôi phải sử dụng TextBox với 'UpdateSourceTrigger of' Explicit ', nhưng tôi có cần phải gọi' UpdateSource() 'cho mỗi người trong số họ không? ví dụ:UpdateSourceTrigger = Rõ ràng

<TextBox Height="23" 
    HorizontalAlignment="Left" 
    Margin="206,108,0,0" 
    Text="{Binding Path=Definition, UpdateSourceTrigger=Explicit}" 
    Name="tbDefinitionFolder" 
    VerticalAlignment="Top" 
    Width="120" /> 

<TextBox Height="23" 
    HorizontalAlignment="Left" 
    Margin="206,108,0,0" 
    Text="{Binding Path=Release, UpdateSourceTrigger=Explicit}" 
    Name="tbReleaseFolder" 
    VerticalAlignment="Top" 
    Width="120" /> 

...

BindingExpression be = tbDefinitionFolder.GetBindingExpression(TextBox.TextProperty); 
be.UpdateSource(); 
BindingExpression be2 = tbReleaseFolder.GetBindingExpression(TextBox.TextProperty); 
be2.UpdateSource(); 

Trả lời

4

Một phương pháp khác có thể được thiết lập UpdateSourceTrigger của bạn để PropertyChanged.

Và sau đó kế thừa VM của bạn từ cả INotifyPropertyChanged và IDataErrorInfo. Dưới đây là ví dụ ...

public class MyViewModel : INotifyPropertyChanged, IDataErrorInfo 
{ 
    private string myVar; 
    public string MyProperty 
    { 
     [DebuggerStepThrough] 
     get { return myVar; } 
     [DebuggerStepThrough] 
     set 
     { 
      if (value != myVar) 
      { 
       myVar = value; 
       OnPropertyChanged("MyProperty"); 
      } 
     } 
    } 
    private void OnPropertyChanged(string prop) 
    { 
     if(PropertyChanged!=null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(pro)); 
     } 
    } 
    public event PropertyChangedEventHandler PropertyChanged; 
    public string Error 
    { 
     get { return String.Empty; } 
    } 
    public string this[string columnName] 
    { 
     get 
     { 
      if (columnName == "MyProperty") 
      { 
       if (String.IsNullOrEmpty(MyProperty)) 
       { 
        return "Should not be blank"; 
       } 
      } 
      return null; 
     } 
    } 
} 

Giả sử rằng một trong các Hộp văn bản của bạn bị ràng buộc thành 'MyProperty' như đã tuyên bố ở trên. Trình chỉ mục được thực hiện trong IDataErrorInfo và được gọi khi thay đổi 'MyProperty'. Trong phần chỉ mục, bạn có thể thực hiện kiểm tra nếu giá trị rỗng và trả về một chuỗi lỗi. Nếu chuỗi lỗi là không null, người dùng nhận được một adorner đẹp trên TextBox như một gợi ý trực quan. Vì vậy, bạn đang ở trong một lần thực hiện xác thực và cung cấp trải nghiệm giao diện người dùng.

Tất cả điều này là miễn phí nếu bạn sử dụng hai giao diện được mã hóa ở trên và sử dụng UpdateSourceTrigger = PropertyChanged. Việc sử dụng UpdateSourceTrigger = Explicit là quá mức cần thiết để cung cấp xác thực mà bạn đã mô tả.

Các XAML cho TextBox sẽ ...

<TextBox DataContext="{StaticResource Vm}" Text="{Binding MyProperty, 
       UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True, 
       NotifyOnSourceUpdated=True, Mode=TwoWay}" Width="200" Height="25"/> 
+1

+1 vì loại xác thực dữ liệu này nên được thực hiện trong ViewModel với 'IDataErrorInfo' – Rachel

+1

Cảm ơn Garry Ive đã thực hiện nó như bạn đã đề xuất, vấn đề hiện tại của tôi là khi hộp thoại bắt đầu hộp văn bản có lỗi là màu đỏ? –

+0

@Rachel Tôi không hiểu tại sao cách tiếp cận của anh ấy vẫn đang cập nhật nguồn mà không cần gọi 'UpdateSource()'. – Igor

4

Nếu bạn sử dụng Explicit bạn cần phải gọi UpdateSource.

Tôi không chắc liệu đây có phải là cách tiếp cận tốt nhất với những gì bạn cố gắng thực hiện hay không, tôi không bao giờ sử dụng Explicit, tôi liên kết với bản sao của đối tượng nếu tôi không muốn thay đổi ngay lập tức hoặc tôi lưu trữ một bản sao và hoàn nguyên mọi thứ trở lại nếu các chỉnh sửa được hủy bỏ.

+0

Vì vậy, nếu bạn có biểu mẫu có nhiều hộp chỉnh sửa cần được kiểm tra khi người dùng nhấn 'gửi' (Chẳng hạn như biểu mẫu chi tiết bảo hiểm xe hơi), bạn sẽ thiết kế nó như thế nào? –

+0

@ChrisMilburn: Tôi có thể thêm [quy tắc xác thực] (http://msdn.microsoft.com/en-us/library/system.windows.controls.validationrule.aspx) để các ràng buộc và sau đó xem nếu mọi kiểm soát là hợp lệ trước khi thực sự tiến hành. [Đây sẽ là một số bài viết về vấn đề này] (http://msdn.microsoft.com/en-us/magazine/ff714593.aspx). –

-1

Nó sẽ đơn giản hơn chỉ cần đặt nó vào UpdateSourceTrigger=PropertyChanged mặc dù nó sẽ cập nhật các biến tiềm ẩn mỗi lần thay đổi giá trị (đối với mỗi chữ cái đầu vào)

1

Có một số lý do tốt để sử dụng UpdateSourceTrigger = Explicit, thay vì giá trị khác. Hãy tưởng tượng rằng bạn phải kiểm tra nếu giá trị đã nhập là duy nhất, sẽ được thực hiện bằng cách đọc cơ sở dữ liệu. Điều đó có thể mất một thời gian, thậm chí 0,3 giây là không thể chấp nhận được. Khi sử dụng PropertyChanged, kiểm tra cơ sở dữ liệu này sẽ được thực hiện mỗi khi người dùng nhấn phím, điều này làm cho giao diện người dùng vô cùng không phản hồi. Điều tương tự cũng xảy ra nếu UpdateSourceTrigger = LostFocus và người dùng sẽ nhanh chóng chuyển đổi giữa các điều khiển (nếu bạn giữ Tab, có tia chớp nhanh giữa các điều khiển). Vì vậy, mục tiêu của chúng tôi là để xác nhận tất cả mọi thứ cùng một lúc tại thời điểm quan trọng (thường là trước khi dữ liệu được lưu). Cách tiếp cận này sẽ cần mã tối thiểu phía sau, điều này sẽ đẩy dữ liệu từ chế độ xem đến xem mô hình và buộc xác nhận. Không có mã xác nhận hoặc logic ứng dụng khác bên trong mã phía sau, vì vậy những người thuần túy MVVM có thể tương đối bình tĩnh. Tôi đã tạo ra ví dụ đầy đủ chức năng trong VB.NET, sử dụng Caliburn.Micro cho MVVM và IoC. Bạn có thể tải xuống tại đây: https://drive.google.com/file/d/0BzdqT0dfGkO3OW5hcjdBOWNWR2M