2013-02-05 34 views
6

Tôi đã một usercontrol tùy chỉnh được gọi SongDescription:WPF Binding để UserControl Tuỳ chỉnh DependencyProperty

<UserControl x:Class="DPTestAp.SongDescription" ...> 
    <Grid x:Name="LayoutRoot"> 
     <DockPanel Height="50"> 
      <TextBlock x:Name="title" Text="{Binding name}" Width="100" Height="30"/> 
      <TextBox x:Name="lyrics"/> 
     </DockPanel> 
    </Grid> 
</UserControl> 

tôi đã thêm thuộc tính phụ thuộc với nó:

public partial class SongDescription : UserControl 
{ 
    public static readonly DependencyProperty SongProperty = DependencyProperty.Register("Song", typeof(Song), typeof(SongDescription)); 

    public Song Song 
    { 
     get 
     { 
      return (Song)GetValue(SongProperty); 
     } 
     set 
     { 
      SetValue(SongProperty, value); 
      updateLyrics() 
     } 
    } 

    private void updateLyrics() 
    { 
     lyrics.Text = Song.lyrics; 
    } 

    public SongDescription() 
    { 
     InitializeComponent(); 
    } 
} 

Câu hỏi đặt ra là: làm thế nào để ràng buộc một cái gì đó để SongProperty này? tôi sử dụng SongDescription trong cửa sổ chính của tôi như thế này:

<local:SongDescription x:Name="songDescription" Song="{Binding DataContext}"/> 

tôi không thể làm cho TextBox tôi lyrics chương lời bài hát. Trong cửa sổ chính tôi đã cố gắng để thiết lập DataContext để songDescription, như thế này:

songDescription.DataContext = new Song() { name="Home", lyrics="Hold on, to me as we go" }; 

hoặc để bản thân cửa sổ như thế này:

DataContext = new Song() { name="Home", lyrics="Hold on, to me as we go" }; 

Tôi thậm chí đã cố gắng để làm cho Sông một nguồn lực và ràng buộc nó vào SongProperty như thế này :

<Window.Resources> 
    <local:Song x:Key="res" name="Home" lyrics="Hold on, to me as we go"/> 
</Window.Resources> 
<Grid> 
    <local:SongDescription x:Name="songDescription" Song="{StaticResource res}"/> 
</Grid> 

Không có gì hữu ích. TextBlock title liên kết tên bài hát tốt. Nhưng tôi không thể gọi phương thức updateLyrics(). (Trong cuộc sống thực, phương pháp này phức tạp hơn, vì vậy tôi không thể sử dụng Binding như tên).

Cảm ơn bạn!

Trả lời

7

Yup, do đó, đó là một bản ghi nhớ với các thuộc tính phụ thuộc. Bạn không bao giờ đặt mã xác nhận bên trong các phương thức accessor (get/set) vì các thuộc tính phụ thuộc được lưu trữ bởi WPF trong một bảng mà chính nó quản lý. Đây là lý do tại sao bạn phải đăng ký các thuộc tính phụ thuộc, về cơ bản tạo các mục trên bảng này để lưu trữ các giá trị liên kết với mỗi thuộc tính và khi bạn sử dụng 'GetValue'/'SetValue', bạn đang cập nhật các mục trên bảng này liên quan đến cách WPF có thể quản lý các ràng buộc dữ liệu nói chung).

Kết quả của điều này là WPF có thể (và sẽ) hoàn toàn bỏ qua người truy cập thuộc tính của bạn vì nó có quyền truy cập trực tiếp vào dữ liệu thực. Tại sao nó nên sử dụng accessors của bạn nếu nó chỉ có thể đi trực tiếp đến dữ liệu. Thay vào đó, bạn cần phải thực hiện chức năng gọi lại 'PropertyChanged' hoặc một số phương thức được phê chuẩn của WPF để xác thực, nhưng không bao giờ làm điều đó trong các trình truy cập của bạn.

Xem:

http://msdn.microsoft.com/en-us/library/ms752914.aspx

+0

Cảm ơn bạn! –

+0

nhưng sau đó, là 'PropertyChanged' gọi lại, tôi sẽ không thể cập nhật bất kỳ điều khiển, bởi vì nó là một chức năng chia sẻ! –

2

Ngoài câu trả lời sircodesalot, bạn không bị ràng buộc về lời bài hát textbox của bạn. Ngoài ra, kể từ khi bài hát của bạn bị ràng buộc là một lớp, bạn sẽ cần phải xác định đường dẫn đầy đủ cho các thuộc tính mà bạn muốn hiển thị trong các hộp như "Path = Song.Lyrics".

Một điều nữa cần lưu ý là với các thuộc tính phụ thuộc; chế độ của bạn sẽ được chuyển sang chế độ mặc định để trường văn bản có thể chỉnh sửa được thực hiện trừ khi bạn thay đổi nó. Thứ ba, nếu bạn đang sử dụng MVVM, bạn chỉ cần bối cảnh cửa sổ chính của mình được đặt thành kiểu xem và có thuộc tính Bài hát phù hợp để ràng buộc.