2010-05-27 24 views
8

này bắt đầu với hành vi kỳ lạ mà tôi nghĩ đã được gắn liền với thực hiện của tôi ToString(), và tôi đã hỏi câu hỏi này: Why won't WPF databindings show text when ToString() has a collaborating object?Hành vi ràng buộc WPF khác nhau khi thuộc tính bị ràng buộc được khai báo là giao diện so với loại lớp học như thế nào?

Hóa ra không có gì để làm với cộng tác viên và là tái sản xuất.

Khi tôi liên kết Label.Content với thuộc tính của DataContext được khai báo là loại giao diện, ToString() được gọi trên đối tượng thời gian chạy và nhãn hiển thị kết quả.

Khi tôi liên kết TextBlock.Text với cùng một thuộc tính, ToString() không bao giờ được gọi và không có gì được hiển thị. Nhưng, nếu tôi thay đổi thuộc tính được khai báo thành triển khai cụ thể của giao diện, nó hoạt động như mong đợi.

Đây có phải là do thiết kế không? Nếu vậy, bất kỳ ý tưởng tại sao?

Để tái sản xuất:

  • Tạo một ứng dụng WPF mới (NET 3.5 SP1)
  • Thêm các lớp sau:
public interface IFoo 
{ 
    string foo_part1 { get; set; } 
    string foo_part2 { get; set; } 
} 

public class Foo : IFoo 
{ 
    public string foo_part1 { get; set; } 

    public string foo_part2 { get; set; } 

    public override string ToString() 
    { 
     return foo_part1 + " - " + foo_part2; 
    } 
} 
public class Bar 
{ 
    public IFoo foo 
    { 
     get { return new Foo {foo_part1 = "first", foo_part2 = "second"}; } 
    } 
} 
  • Đặt XAML của Window1 tới:

    <Window x:Class="WpfApplication1.Window1" 
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
        Title="Window1" Height="300" Width="300"> 
        <StackPanel> 
         <Label Content="{Binding foo, Mode=Default}"/> 
         <TextBlock Text="{Binding foo, Mode=Default}"/> 
        </StackPanel> 
    </Window> 
    
  • trong Window1.xaml.cs:

public partial class Window1 : Window 
{ 
    public Window1() 
    { 
     InitializeComponent(); 
     DataContext = new Bar(); 
    } 
} 

Khi bạn chạy ứng dụng này, bạn sẽ thấy văn bản chỉ một lần (ở trên cùng, trong nhãn). Nếu bạn thay đổi loại tài sản foo trên Bar lớp thành Foo (thay vì IFoo) và chạy lại ứng dụng, bạn sẽ thấy văn bản trong cả hai điều khiển.

Trả lời

3

Có bạn đã đúng. Rõ ràng thuộc tính ContentControl.Content được thực hiện khác với thuộc tính TextBlock.Text. Một sự khác biệt rõ ràng của khóa học là ContentControl sẽ thực sự tạo ra một cá thể TextBlock cho một đối tượng nội dung không phải là Visual và không có DataTemplate. TextBlock thì không. Nó sẽ tự hiển thị văn bản.Trong cả hai trường hợp, các chuỗi được xác định bởi

  1. các IValueConverter (nếu có trong các ràng buộc)
  2. các TypeConverter (nếu tuyên bố)
  3. object.ToString()

Dường như thuật toán này chỉ khác bước 3 giữa TextBlockContentControl như bạn đã hiển thị. Trong khi ContentControl thực sự giải quyết đối tượng đằng sau giao diện, thì TextBlock thì không. Hấp dẫn.

Tôi đoán đây là thứ mà bạn phải sống cùng. Bạn có nhiều lựa chọn bây giờ:

  • Expose một tài sản chuỗi trên giao diện của bạn và liên kết với đó
  • Expose đối tượng dữ liệu như là một lớp bê tông thay vì như một giao diện
  • Sử dụng một ContentControl thay vì một TextBlock
  • cung cấp một IValueConverter và sử dụng nó trong các ràng buộc
  • cung cấp một TypeConverter cho giao diện của bạn
  • làm cái gì khác (có lẽ mor e)
8

Tôi biết chủ đề này cũ nhưng tôi đã tìm thấy giải pháp cho vấn đề này. Sử dụng thuộc tính StringFormat trên liên kết:

<Window x:Class="WpfApplication1.Window1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="Window1" Height="300" Width="300"> 
    <StackPanel> 
     <Label Content="{Binding foo, Mode=Default}"/> 
     <TextBlock Text="{Binding foo, Mode=Default, StringFormat={}{0}}"/> 
    </StackPanel> 
</Window> 
+0

Henrik, [ai đó đã hỏi một câu hỏi rất giống] (http://stackoverflow.com/questions/16309863/binding-to-interface-typed-properties), và khi tôi liên kết họ với người này, họ nói câu trả lời của bạn đã giải quyết được vấn đề của họ. Câu hỏi đó là của bạn để trả lời nếu bạn thích; Tôi không muốn nhận tín dụng khi tất cả những gì tôi làm là tìm một câu hỏi tương tự :) – shambulator

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