2009-10-06 34 views
16

Cách thích hợp để triển khai Thuộc tính tùy chỉnh trong Silverlight UserControls là gì?Silverlight UserControl Custom Property Binding

Mỗi "Trang" trong Silverlight về mặt kỹ thuật là một UserControl (chúng được bắt nguồn từ lớp UserControl). Khi tôi nói UserControl ở đây, tôi có nghĩa là một UserControl tùy chỉnh sẽ được sử dụng bên trong nhiều trang khác nhau trong nhiều kịch bản khác nhau (tương tự như một UserControl ASP.NET).

Tôi muốn Custom UserControl hỗ trợ Binding và không dựa vào Tên của thuộc tính mà nó ràng buộc, luôn giống nhau. Thay vào đó, tôi muốn UserControl chính nó có một thuộc tính mà các điều khiển bên trong UserControl liên kết với, và các ViewModels bên ngoài UserControl cũng liên kết với. (vui lòng xem ví dụ bên dưới)

Ràng buộc trong công việc UserControl, Ràng buộc trong các công trình MainPage, Ràng buộc tôi thiết lập giữa MainPage và UserControl không hoạt động. Cụ thể dòng này:

<myUserControls:MyCustomUserControl x:Name="MyCustomControl2" 
    SelectedText="{Binding MainPageSelectedText, Mode=TwoWay}" 
    Width="200" Height="50" /> 

dụ đầu ra:
alt text

MainPage.xaml

<UserControl x:Class="SilverlightCustomUserControl.MainPage" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:myUserControls="clr-namespace:SilverlightCustomUserControl" 
    mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480" 
    DataContext="{Binding RelativeSource={RelativeSource Self}}"> 
    <Canvas x:Name="LayoutRoot"> 
    <StackPanel Orientation="Vertical"> 
     <TextBlock Text="UserControl Binding:" Width="200"></TextBlock> 
     <myUserControls:MyCustomUserControl x:Name="MyCustomControl2" SelectedText="{Binding MainPageSelectedText, Mode=TwoWay}" Width="200" Height="50" /> 
     <TextBlock Text="MainPage Binding:" Width="200"></TextBlock> 
     <TextBox Text="{Binding MainPageSelectedText, Mode=TwoWay}" Width="200"></TextBox> 
     <Border BorderBrush="Black" BorderThickness="1"> 
     <TextBlock Text="{Binding MainPageSelectedText}" Width="200" Height="24"></TextBlock> 
     </Border> 
    </StackPanel> 
    </Canvas> 
</UserControl> 

MainPage.xaml.cs

namespace SilverlightCustomUserControl 
{ 
public partial class MainPage : UserControl, INotifyPropertyChanged 
{ 
    //NOTE: would probably be in a ViewModel 
    public string MainPageSelectedText 
    { 
    get { return _MainPageSelectedText; } 
    set 
    { 
    string myValue = value ?? String.Empty; 
    if (_MainPageSelectedText != myValue) 
    { 
    _MainPageSelectedText = value; 
    OnPropertyChanged("MainPageSelectedText"); 
    } 
    } 
    } 
    private string _MainPageSelectedText; 


    public MainPage() 
    { 
    InitializeComponent(); 
    } 


    #region INotifyPropertyChanged Members 

    public event PropertyChangedEventHandler PropertyChanged; 

    protected virtual void OnPropertyChanged(string name) 
    { 
    PropertyChangedEventHandler ph = this.PropertyChanged; 

    if (ph != null) 
    ph(this, new PropertyChangedEventArgs(name)); 
    } 

    #endregion 
} 
} 

MyCustomUserControl.xaml

01.
<UserControl 
    x:Class="SilverlightCustomUserControl.MyCustomUserControl" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    DataContext="{Binding RelativeSource={RelativeSource Self}}"> 
    <Grid> 
    <StackPanel> 
     <TextBox Text="{Binding SelectedText, Mode=TwoWay}" /> 
     <Border BorderBrush="Black" BorderThickness="1"> 
     <TextBlock Text="{Binding SelectedText}" Height="24"></TextBlock> 
     </Border> 
    </StackPanel> 
    </Grid> 
</UserControl> 

MyCustomUserControl.xaml.cs

namespace SilverlightCustomUserControl 
{ 
public partial class MyCustomUserControl : UserControl 
{ 
    public string SelectedText 
    { 
    get { return (string)GetValue(SelectedTextProperty); } 
    set { SetValue(SelectedTextProperty, value); } 
    } 

    public static readonly DependencyProperty SelectedTextProperty = 
    DependencyProperty.Register("SelectedText", typeof(string), typeof(MyCustomUserControl), new PropertyMetadata("", SelectedText_PropertyChangedCallback)); 


    public MyCustomUserControl() 
    { 
    InitializeComponent(); 
    } 

    private static void SelectedText_PropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
    //empty 
    } 
} 
} 

Tài liệu tham khảo (làm thế nào tôi có này đến nay):

DependencyPropertys sử dụng: http://geekswithblogs.net/thibbard/archive/2008/04/22/wpf-custom-control-dependency-property-gotcha.aspx

DependencyPropertys sử dụng, thêm x: Đặt tên cho usercontrol của bạn - thêm Ràng buộc với ElementName, đặt thuộc tính tùy chỉnh một lần nữa trong phương thức PropertyChangedCallback:

không sử dụng các thuộc tính tùy chỉnh, dựa vào tên DataContext cơ bản (Tôi không thích giải pháp này): wpf trouble using dependency properties in a UserControl

+0

Nếu bạn vẫn đang tìm kiếm câu trả lời, bạn có thể tham khảo bài viết này [Liên kết tài sản tùy chỉnh Silverlight UserControl] (http://www.dotnetspark.com/kb/4664-silverlight-usercontrol-custom-property.aspx) –

Trả lời

7

tôi hiểu nó như là lý do kiểm soát của bạn không nhận được giá trị mới từ trang Maim là rằng bạn đang thiết lập DataContext của điều khiển. Nếu bạn không có thì DataContext của điều khiển sẽ được thừa kế từ cha mẹ của nó, trang chính trong trường hợp này.

Để làm việc này, tôi đã xóa bạn kiểm soát cài đặt DataContext, thêm x: Tên cho mỗi điều khiển và đặt liên kết trong hàm tạo của điều khiển bằng cách sử dụng phương thức [name] .SetBinding.

Tôi đã liên kết trong ctor vì tôi không thể tìm ra cách thiết lập thuộc tính Nguồn của liên kết khai báo trong xaml thành Self. tức là {Binding SelectedText, Mode = TwoWay, Source = [Tự ở đây một số cách]}. Tôi đã thử sử dụng RelativeSource = {RelativeSource Self} mà không có niềm vui.

LƯU Ý: Tất cả điều này là SL3.

+0

Có! những người đã được các bước chính xác của tôi kể từ khi đăng bài này là tốt! Tôi sẽ đăng một số mã nó một chút. Cảm ơn đã giúp đỡ. p.s. RelativeSource = Tự không hoạt động vì DataContext trở thành TextBox, không phải là UserControl. –

+0

Tất nhiên. Điều đó có ý nghĩa tổng thể. Cảm ơn vì đã cho tôi biết. – voiddog

4

Vấn đề được UserControl được ném một lỗi DataBinding (có thể nhìn thấy trong cửa sổ Output khi gỡ lỗi)

Bởi vì DataContext của UserControl được thiết lập để "tự" trong XAML của riêng mình, nó đang tìm kiếm các MainPageSelectedText trong của nó bối cảnh của chính nó (nó không tìm kiếm MainPageSelectedText trong "MainPage" là nơi bạn có thể nghĩ rằng nó sẽ nhìn, bởi vì khi bạn đang viết/nhìn vào mã đó là gì trong "ngữ cảnh")

I đã có thể có được điều này "làm việc" bằng cách thiết lập các ràng buộc trong mã phía sau. Đặt ràng buộc trong mã phía sau là cách duy nhất để thiết lập UserControl là "Nguồn" của ràng buộc. Nhưng điều này chỉ hoạt động nếu Binding là TwoWay. OneWay ràng buộc sẽ phá vỡ mã này. Một giải pháp tốt hơn hoàn toàn là tạo một Silverlight Điều khiển, không phải là UserControl.

Xem thêm:

http://social.msdn.microsoft.com/Forums/en-US/silverlightcontrols/thread/052a2b67-20fc-4f6a-84db-07c85ceb3303

http://msdn.microsoft.com/en-us/library/cc278064%28VS.95%29.aspx

MyCustomUserControl.xaml

<UserControl 
    x:Class="SilverlightCustomUserControl.MyCustomUserControl" 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"> 
<Grid> 
    <StackPanel> 
    <TextBox x:Name="UserControlTextBox" /> 
    <Border BorderBrush="Black" BorderThickness="1"> 
    <TextBlock x:Name="UserControlTextBlock" Height="24"></TextBlock> 
    </Border> 
    </StackPanel> 
</Grid> 
</UserControl> 

MyCustomUserControl.xaml.cs

namespace SilverlightCustomUserControl 
{ 
public partial class MyCustomUserControl : UserControl 
{ 

    public string SelectedText 
    { 
    get { return (string)GetValue(SelectedTextProperty); } 
    set { SetValue(SelectedTextProperty, value); } 
    } 

    public static readonly DependencyProperty SelectedTextProperty = 
    DependencyProperty.Register("SelectedText", typeof(string), typeof(MyCustomUserControl), new PropertyMetadata("", SelectedText_PropertyChangedCallback)); 


    public MyCustomUserControl() 
    { 
    InitializeComponent(); 

       //SEE HERE 
    UserControlTextBox.SetBinding(TextBox.TextProperty, new Binding() { Source = this, Path = new PropertyPath("SelectedText"), Mode = BindingMode.TwoWay }); 
    UserControlTextBlock.SetBinding(TextBlock.TextProperty, new Binding() { Source = this, Path = new PropertyPath("SelectedText") }); 
       //SEE HERE 
    } 

    private static void SelectedText_PropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
    //empty 
    } 

} 
} 
0

Thay vì ràng buộc bối cảnh dữ liệu tự, bạn có thể thiết lập các ràng buộc trong XAML bằng cách thêm một x:Name cho người dùng điều khiển và sau đó ràng buộc trong XAML điều khiển người dùng sau:

<UserControl 
    x:Class="SilverlightCustomUserControl.MyCustomUserControl" 
    x:Name="myUserControl 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"> 
    <Grid> 
     <StackPanel> 
      <TextBox Text="{Binding SelectedText, ElementName=myUserContol, Mode=TwoWay}" /> 
      <Border BorderBrush="Black" BorderThickness="1"> 
       <TextBlock Text="{Binding SelectedText,ElementName=myUserControl}" Height="24"></TextBlock> 
      </Border> 
     </StackPanel> 
    </Grid> 
</UserControl> 
Các vấn đề liên quan