2009-03-02 54 views
17

Có bất kỳ khung ràng buộc dữ liệu nào (BCL hay cách khác) cho phép ràng buộc giữa bất kỳ hai thuộc tính CLR nào thực hiện INotifyPropertyChangedINotifyCollectionChanged? Nó có vẻ là người ta có thể làm điều gì đó như thế này:Ràng buộc dữ liệu Thuộc tính POCO

var binding = new Binding(); 
binding.Source = someSourceObject; 
binding.SourcePath = "Customer.Name"; 
binding.Target = someTargetObject; 
binding.TargetPath = "Client.Name"; 
BindingManager.Bind(binding); 

đâu someSourceObjectsomeTargetObject chỉ POCOs mà thực hiện INotifyPropertyChanged. Tuy nhiên, tôi không biết về bất kỳ sự hỗ trợ nào của BCL cho việc này, và tôi không chắc chắn liệu có các khung công tác hiện có cho phép điều này hay không.

CẬP NHẬT: Do không có sẵn thư viện, tôi đã tự mình thực hiện để tự viết. Nó có sẵn here.

Cảm ơn

Trả lời

10

Tôi đã viết Truss để lấp đầy khoảng trống.

1

AutoMapper có thể sao chép các giá trị giữa hai trường hợp, nhưng bạn phải viết mã của riêng bạn để làm cho điều này xảy ra tự động.

1

Có thể Bindable LINQ hoặc continuous linq có thể trợ giúp tại đây. Nếu bạn đang cố gắng thêm các thuộc tính mô hình thực sự là "các thuộc tính có nguồn gốc" của dữ liệu thực tế, cập nhật, để giúp giao diện người dùng dễ ràng hơn, thì hai khung công tác này sẽ giúp ích.

7

Tôi không biết về bất kỳ thư viện nào thực hiện điều này - nhưng bạn có thể viết của riêng bạn khá dễ dàng.

Dưới đây là một cơ sở Tôi gõ lên trong một vài phút mà thiết lập hai dữ liệu theo cách ràng buộc giữa hai thuộc tính đơn giản:

public static class Binder 
{ 

    public static void Bind(
     INotifyPropertyChanged source, 
     string sourcePropertyName, 
     INotifyPropertyChanged target, 
     string targetPropertyName) 
    { 
     var sourceProperty 
      = source.GetType().GetProperty(sourcePropertyName); 
     var targetProperty 
      = target.GetType().GetProperty(targetPropertyName); 

     source.PropertyChanged += 
      (s, a) => 
      { 
       var sourceValue = sourceProperty.GetValue(source, null); 
       var targetValue = targetProperty.GetValue(target, null); 
       if (!Object.Equals(sourceValue, targetValue)) 
       { 
        targetProperty.SetValue(target, sourceValue, null); 
       } 
      }; 

     target.PropertyChanged += 
      (s, a) => 
      { 
       var sourceValue = sourceProperty.GetValue(source, null); 
       var targetValue = targetProperty.GetValue(target, null); 
       if (!Object.Equals(sourceValue, targetValue)) 
       { 
        sourceProperty.SetValue(source, targetValue, null); 
       } 
      }; 
    } 
} 

Tất nhiên, mã này thiếu một vài niceties. Những điều cần thêm bao gồm

  • Kiểm tra rằng sourcetarget được giao
  • Kiểm tra rằng các thuộc tính xác định bởi sourcePropertyNametargetPropertyName tồn tại
  • Kiểm tra cho loại tương thích giữa hai thuộc tính

Ngoài ra, Reflection tương đối chậm (mặc dù điểm chuẩn trước khi loại bỏ nó, nó không phải là rằng chậm), vì vậy bạn có thể muốn sử dụng được biên dịch thay vào đó.

Cuối cùng, do việc xác định các thuộc tính theo chuỗi là dễ bị lỗi, bạn có thể sử dụng các biểu thức LINQ và các phương thức mở rộng thay thế. Sau đó, thay vì viết

Binder.Bind(source, "Name", target, "Name") 

bạn có thể viết

source.Bind(Name => target.Name); 
+0

Tôi thực sự hỏi vì tôi đang cân nhắc việc viết của riêng mình. Không muốn phát minh lại bánh xe và tất cả ... cảm ơn. –

+0

Cập nhật: Tôi đã liên kết với thư viện của tôi trong câu hỏi. –

+0

Tôi cần một lớp dữ liệu barebone đơn giản cho dự án hiện tại của tôi-trong-một-vội vàng, và một ở trên gần như phù hợp với những gì tôi cần. Tôi chỉ thay thế các tên thuộc tính được sử dụng với Reflection bởi hai đại biểu Action trong đó tôi nhận được/thiết lập từ POCO và áp dụng các phép biến đổi và định dạng. Tôi chắc chắn sẽ cố gắng hết sức để Truss trong một dự án tiếp theo, bởi vì nó có vẻ thực sự gây trở ngại cho tôi. – Larry

-2

Nếu bạn định nghĩa các thuộc tính của bạn như DependencyProperty của bạn có thể làm điều đó. Cả WF và WPF đều thực hiện nó (liên kết đầu tiên là cho WPF. Đối với WF nó là this một) vì vậy bạn cần phải quyết định nên sử dụng gì - nhưng cả hai đều đủ cho nhu cầu của bạn.

+2

DependencyProperty ngụ ý kế thừa từ DependencyObject, không phải là POCO. –

+1

+1. Nói cách khác, "Bạn không thể với poco, chỉ có DP." – Will

+0

Eh? Không chắc chắn logic của bạn là gì để bỏ phiếu cho Will. Cả hai đề xuất sẽ không đủ cho nhu cầu của tôi vì không có đề xuất nào liên quan đến POCO. Một bài đăng khác đã cho thấy bạn có thể làm điều đó với POCO - tôi chỉ yêu cầu một khung làm việc nâng khó khăn. –

0

Tôi đã viết một dự án Bind nhỏ với sự hỗ trợ đầy đủ cho việc liên kết giữa các thuộc tính không đồng bộ với các hành động ràng buộc không đồng bộ. Sintax không thể đơn giản hơn:

//Two way binding between neasted properties: 
Bind.TwoWay(()=> client.Area.Data.Name == this.AreaName); 

//On change action execute: 
Bind 
    .OnChange(()=> client.Personal.Name) 
    .Do(x => clientName = x); 
Các vấn đề liên quan