2009-09-11 41 views
7

Vì vậy, tôi đang làm việc thông qua dự án WPF đầu tiên của tôi và tôi thích những gì tôi thấy cho đến nay. Có nhiều đường cong học tập hơn so với những gì tôi dự đoán, nhưng tuy nhiên WPF là khá mát mẻ. Tuy nhiên, tôi đang đấu tranh một chút với các khái niệm ràng buộc dữ liệu. Một câu hỏi cụ thể mà tôi có là làm thế nào để tôi thực hiện các khai báo ràng buộc dữ liệu của tôi refactor an toàn? Hãy xem xét ví dụ này.Làm thế nào để tôi thực hiện các ràng buộc dữ liệu WPF refactor an toàn?

public class MyDataObject 
{ 
    public string FooProperty { get; set; } 
} 

void Bind() 
{ 
    var gridView = myListView.View as GridView; 
    gridView.Columns.Clear(); 
    gridView.Columns.Add(
    new GridViewColumn() 
     { 
     Header = "FooHeader", 
     DisplayMember = new Binding("FooProperty") 
     } 
    ); 
    List<MyDataObject> source = GetData(); 
    myListView.ItemsSource = source; 
} 

Vì vậy, nếu tôi đổi tên FooProperty trên đối tượng dữ liệu của mình thành một thứ gì khác thì sao? Các ràng buộc dữ liệu sẽ không hợp lệ và tôi sẽ không nhận được một lỗi biên dịch kể từ khi ràng buộc đã được tuyên bố thông qua văn bản chỉ. Có cách nào để làm cho ràng buộc thêm một chút refactor an toàn?

Trả lời

3

Bạn có thể sử dụng một biểu thức lambda để diễn tả tên thuộc tính, thay vì sử dụng tên trực tiếp:

protected static string GetPropertyName<TSource, TResult>(Expression<Func<TSource, TResult>> expression) 
    { 
     if (expression.NodeType == ExpressionType.Lambda && expression.Body.NodeType == ExpressionType.MemberAccess) 
     { 
      PropertyInfo prop = (expression.Body as MemberExpression).Member as PropertyInfo; 
      if (prop != null) 
      { 
       return prop.Name; 
      } 
     } 
     throw new ArgumentException("expression", "Not a property expression"); 
    } 

Bạn sẽ sử dụng nó như thế:

... 
DisplayMember = new Binding(GetPropertyName((MyDataObject o) => o.FooProperty)) 
... 

OK, đó là một chút dài dòng ... Nếu bạn muốn một cái gì đó ngắn hơn, bạn cũng có thể tạo phương thức trợ giúp:

public Binding CreateBinding<TSource, TResult>(Expression<Func<TSource, TResult>> expression) 
{ 
    return new Binding(GetPropertyName(expression)) 
} 

... 
DisplayMember = CreateBinding((MyDataObject o) => o.FooProperty) 
... 

Điều đó w ay, việc tái cấu trúc sẽ hoạt động tốt nếu bạn đổi tên thuộc tính (ngoại trừ trong XAML tất nhiên ...)

+0

Rất thông minh. Yeah, xaml vẫn sẽ là một vấn đề, nhưng ít nhất trong kịch bản trước mắt của tôi, tôi phải xây dựng các cột động một cách tự động sao cho không có mối quan tâm nào vào lúc này. Cảm ơn! –

0

Bạn có thể sử dụng phản chiếu để xác định tên của thuộc tính của mình. Tất nhiên, điều này là vấn đề nếu bạn có nhiều hơn một ràng buộc cho mỗi lớp, vì vậy có lẽ bổ sung bằng cách sử dụng các thuộc tính tùy chỉnh (cũng có sẵn thông qua sự phản chiếu) để có được 'gợi ý' như trường ràng buộc đúng mà thuộc tính được đặt tên sẽ được ràng buộc.

Điều đó rất tốt có thể kết thúc chỉ cần di chuyển chuỗi ma thuật không thể tái cấu trúc sang một phần khác của ứng dụng, mặc dù tôi không thể nói rằng tôi đã thử điều này và đã làm việc.

+0

Tái cấu trúc là một thứ xảy ra vào lúc thiết kế, trong khi phản ánh xảy ra vào thời gian chạy. (Trên thực tế trong ngôn ngữ 'io', tái cấu trúc có thể xảy ra trong thời gian chạy, nhưng đó là một câu chuyện khác!) –

+0

Tất nhiên, nhưng khi tôi hiểu câu hỏi, tái cấu trúc sẽ không nắm bắt 'chuỗi ma thuật' của FooProperty trong ràng buộc, vì vậy tài sản sẽ thay đổi và ràng buộc sẽ không; bằng cách lấy đúng chuỗi tại thời gian chạy qua phản xạ, bạn luôn nhìn vào thế giới gần đây nhất và không phụ thuộc vào việc đảm bảo bạn đã thay đổi tất cả các hằng số của mình. – Mikeb

+0

@Mikeb - nó phụ thuộc vào công cụ tái cấu trúc mà bạn sử dụng. –

2

Tái cấu trúc dựa trên công cụ hỗ trợ nhận dạng khi một ký hiệu cụ thể trong mã (C#, XAML, config etc ...) đại diện cho số nhận dạng đang được đổi tên. Trong ví dụ bạn đưa ra, chuỗi ký tự "FooProperty" không thể được hiểu là thuộc về MyDataObject mà không có kiến ​​thức đặc biệt về hoạt động bên trong của GridView và mở rộng tất cả các loại khác trong WPF và các khung công tác khác.

Tuy nhiên, trong một DataTemplate, có thể chắc chắn 99%:

<DataTemplate DataType="{x:Type local:MyDataObject}"> 
    <TextBlock Text="{Binding Path=FooProperty}" /> 
</DataTemplate> 

tôi sử dụng (và thề) một plugin IDE gọi ReSharper (aka R #) mà là một rất thông minh về các loại của mọi thứ. Nếu bạn đổi tên FooProperty, R # sẽ tự động đổi tên thuộc tính cho bạn.

Trong ví dụ của bạn, nếu bạn đổi tên thuộc tính, R # sẽ vẫn được sử dụng. Nó tìm thấy tất cả các trường hợp của chuỗi trong chữ (trường hợp của bạn) và bình luận (rất hữu ích nếu bạn đã nhận xét ra một số mã và có thể bỏ ghi chú nó sau này). Bạn được cung cấp chế độ xem dạng cây hiển thị từng chữ trong ngữ cảnh và bạn có thể kiểm tra/bỏ chọn từng tập quán/tệp/thư mục/dự án trước khi tiếp tục.

Nếu ngân sách của bạn cho phép, hãy nhận R #. Nếu ngân sách của bạn không cho phép, hãy tải xuống bản dùng thử và cuối cùng, ngân sách của bạn sẽ tìm phòng. Hãy chắc chắn rằng bạn in ra một bản sao của các phím tắt để cải thiện kinh nghiệm học tập của bạn.

+0

Đề xuất tốt. –

Các vấn đề liên quan