2010-01-26 21 views
7

Tôi đang đi đến điểm trong một ứng dụng WPF, nơi tất cả các ràng buộc trên điều khiển của tôi đang nhận được khá lặp đi lặp lại và cũng có một chút quá tiết. Ngoài ra nếu tôi muốn thay đổi ràng buộc này, tôi sẽ phải thay đổi nó ở nhiều nơi thay vì chỉ một.Bất kỳ cách nào để tái sử dụng Bindings trong WPF?

Có cách nào để viết phần nguồn của liên kết một lần như trong tài nguyên và sau đó tái sử dụng nó bằng cách tham chiếu nó bằng cú pháp nhỏ gọn hơn. Tôi đã nhìn xung quanh cho các khả năng như vậy nhưng tôi đã không tìm thấy nó.

Những gì tôi đang làm gì bây giờ

<StackPanel> 
    <ToggleButton x:Name="someToggleButton" /> 
    <Button Visibility="{Binding ElementName=someToggleButton, Path=IsChecked, Converter={StaticResource BoolToVisibilityConverter}}" /> 
    <Grid Visibility="{Binding ElementName=someToggleButton, Path=IsChecked, Converter={StaticResource BoolToVisibilityConverter}}" /> 
    <TextBox Visibility="{Binding ElementName=someToggleButton, Path=IsChecked, Converter={StaticResource BoolToVisibilityConverter}}" /> 
    <CheckBox Visibility="{Binding ElementName=someToggleButton, Path=IsChecked, Converter={StaticResource BoolToVisibilityConverter}}" /> 
</StackPanel> 

Những gì tôi muốn để có thể làm (Mã giả)

<StackPanel> 
    <StackPanel.Resources> 
     <Variable x:Name="someToggleButtonIsChecked" 
        Type="{x:Type Visibility}" 
        Value="{Binding ElementName=someToggleButton, Path=IsChecked, Converter={StaticResource BoolToVisibilityConverter}}" /> 
    </StackPanel.Resources> 

    <ToggleButton x:Name="someToggleButton" /> 
    <Button Visibility="{VariableBinding someToggleButtonIsChecked}" /> 
    <Grid Visibility="{VariableBinding someToggleButtonIsChecked}" /> 
    <TextBox Visibility="{VariableBinding someToggleButtonIsChecked}" /> 
    <CheckBox Visibility="{VariableBinding someToggleButtonIsChecked}" /> 
</StackPanel> 

Có bất kỳ loại tương tự của tính năng tương tự hoặc kỹ thuật mà sẽ cho phép tôi khai báo nguồn ràng buộc một lần và sau đó sử dụng lại nó?

+0

Tạo mã ??? –

Trả lời

1

Bạn chỉ có thể liên kết thuộc tính someToggleButton 's IsChecked với thuộc tính trên chế độ xem của bạn (DataContext) và sử dụng nó. Nó sẽ giống như thế này:

<StackPanel> 
<ToggleButton x:Name="someToggleButton" IsChecked="{Binding ToggleVisibility, Mode=TwoWay, Converter={StaticResource BoolToVisibilityConverter}}" /> 
<Button Visibility="{Binding ToggleVisibility}" /> 
<Grid Visibility="{Binding ToggleVisibility}" /> 
<TextBox Visibility="{Binding ToggleVisibility}" /> 
<CheckBox Visibility="{Binding ToggleVisibility}" /> 
</StackPanel> 

này sẽ đòi hỏi rằng Window 's DataContext của bạn có một tài sản được gọi ToggleVisibility loại Visibility.

EDIT:

Để eleborate hơn nữa, viewmodel của bạn có thể trông như thế này:

public class SomeViewModel : INotifyPropertyChanged 
{ 

    private Visibility toggleVisibility; 

    public SomeViewModel() 
    { 
     this.toggleVisibility = Visibility.Visible; 
    } 

    public Visibility ToggleVisibility 
    { 
     get 
     { 
      return this.toggleVisibility; 
     } 
     set 
     { 
      this.toggleVisibility = value; 
      RaisePropertyChanged("ToggleVisibility"); 
     } 
    } 

    private void RaisePropertyChanged(string propertyName) 
    { 
     if (this.PropertyChanged != null) 
      this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
    } 

    #region INotifyPropertyChanged Members 

    public event PropertyChangedEventHandler PropertyChanged; 

    #endregion 
} 

Và sau đó bạn sẽ thiết lập một thể hiện của nó như là DataContext trên Window hoặc thậm chí chỉ trên StackPanel

+0

Điều này thực sự tương tự như những gì tôi đã có ban đầu nhưng nó đã được khá nhiều mã để thêm vào mã của tôi phía sau cho chỉ một tài sản duy nhất. Về lâu dài nếu không có giải pháp dựa trên XAML, tôi có thể sẽ quay trở lại để thực hiện nó nhiều hơn một chút MVVM. – jpierson

+0

@Jpierson Bạn thực sự nên quay lại sử dụng MVVM. Tôi có nghĩa là bạn đã có một hộp văn bản, giá trị mà bạn có thể liên kết với viewmodel, và một nút có lệnh bạn cũng có thể liên kết với viewmodel. Theo tôi, viewmodels là đúng cách để đi, trong khi mã trong cửa sổ bạn thì không. –

+0

Tôi sử dụng ViewModels hiện tại trong mã chính của tôi nhưng mã này là trong một Dialog nhỏ và thêm một ViewModel quá nó dường như không cần thiết vì có thực sự là không có "Model" để trở lại ViewModel của tôi. Một vấn đề khác tôi đang gặp phải là có trường hợp mà tôi cần phải chuỗi một BoolToVisibilityConverter và một InverseBoolConverter trong một ràng buộc trên một điều khiển. Bằng cách làm cho một tài sản trong mã của tôi phía sau hoặc trong ViewModel cụ thể gọi là IsNotDeleteMode sẽ làm việc nhưng sau đó tôi có IsAddMode, IsNotAddMode, IsDeleteMode, và IsNotDeleteMode propeties. Có vẻ như một mớ hỗn độn với tôi bất kể nó đi đâu. – jpierson

0

Có cách nào để viết phần nguồn của liên kết một lần như trong một lần nữa không nguồn và sau đó tái sử dụng nó bằng cách tham khảo nó với một cú pháp nhỏ gọn hơn.

Có lẽ bạn có thể làm điều đó với PyBinding. Tôi không biết mức độ khả năng của nó, nhưng tôi sử dụng nó tất cả các thời gian ot tránh chuyển đổi loại. Đây là một ví dụ tôi sử dụng rất nhiều.

Visibility="{p:PyBinding BooleanToVisibility(IsNotNull($[.InstanceName]))}" 
  • BooleanToVisibility là một chức năng tôi đã viết trong IronPython.
  • $ [. InstanceName] liên kết với thuộc tính InstanceName của mục ràng buộc dữ liệu hiện tại.

EDIT: Bạn cũng có thể sử dụng quyền này để liên kết thuộc tính của giao diện người dùng với tài sản của người khác. Dưới đây là một số thông tin từ tệp trợ giúp.

  • $ [NameTextBlock.Văn bản] - Thuộc tính văn bản của phần tử có x: Tên bằng "NameTextBlock"
  • $ [NameTextBlock] - Một phiên bản TextBlock thực tế, chứ không phải một trong các thuộc tính của nó
  • $ [{Self}] - Liên kết với tự. Tương đương với {Binding RelativeSource = {RelativeSource Self}}
  • $ [{Self} .Text] - Thuộc tính Text tự tắt. Tương đương với {Binding Path = Text, RelativeSource = {RelativeSource Tự}}

http://pybinding.codeplex.com/

chưa được kiểm tra lý thuyết

<StackPanel> 
    <ToggleButton x:Name="someToggleButton" /> 
    <Button Visibility="{p:PyBinding BooleanToVisibility($[someToggleButton.IsChecked])}" /> 
    <Grid Visibility="{p:PyBinding BooleanToVisibility($[someToggleButton.IsChecked])}"/> 
    <TextBox Visibility="{p:PyBinding BooleanToVisibility($[someToggleButton.IsChecked])}"/> 
    <CheckBox Visibility="{p:PyBinding BooleanToVisibility($[someToggleButton.IsChecked])}"/> 
</StackPanel> 

Second Cố gắng

<StackPanel> 
    <ToggleButton x:Name="someToggleButton" /> 
    <Button Name="myButton" Visibility="{p:PyBinding BooleanToVisibility($[someToggleButton.IsChecked])}" /> 
    <Grid Visibility="{p:PyBinding $[myButton.Visibility]}"/> 
    <TextBox Visibility="{p:PyBinding $[myButton.Visibility]}"/> 
    <CheckBox Visibility="{p:PyBinding $[myButton.Visibility]}"/> 
</StackPanel> 
+0

Thats khá gọn gàng, và một cái gì đó tôi đã không biết. Vấn đề vẫn là với cách tiếp cận đó là tôi thực sự muốn lưu trữ ràng buộc ở một nơi. Nói ví dụ rằng tại một số điểm tôi muốn sửa đổi khả năng hiển thị của tất cả các điều khiển này được điều khiển khỏi thuộc tính ToggleButton.IsEnabled. Tôi sẽ phải thay đổi nó nhiều nơi và đó là lý do tại sao tôi quan tâm đến việc tuyên bố nó một lần và sau đó tái sử dụng nó. – jpierson

+0

Bạn có thể đặt tên cho Nút của mình và sau đó ràng buộc khả năng hiển thị của tất cả các điều khiển khác với nút đó. Tôi biết nó không chính xác những gì bạn muốn, nhưng nó gần hơn. –

+0

Vâng, tôi cũng đã làm điều đó. Lấy nó đến một cấp độ khác tôi có thể làm cho một điều khiển tùy chỉnh chung chung với một tài sản duy nhất được gọi là một cái gì đó như Value (MyBindingControl ). Sau đó, cho mỗi loại mà tôi muốn sử dụng lại một ràng buộc cho tôi có thể làm cho một lớp học chuyên ngành như StringBindingControl: MyBindingControl . Điều này sau đó có thể được sử dụng như một loại biến mà các điều khiển khác có thể liên kết. Vấn đề chính với kỹ thuật này là rất khó để tái sử dụng trong các kiểu/mẫu chung trong các từ điển tài nguyên vì nó rất có thể sẽ dựa vào các điều khiển được đặt tên. – jpierson

0

Chỉ cần nhìn vào mã gốc , bạn có thể nhóm các phần tử cần thiết vào thùng chứa của riêng mình và sau đó quản lý vùng chứa Visibilit y:

<StackPanel> 
    <ToggleButton x:Name="someToggleButton" /> 
    <StackPanel Visibility="{Binding ElementName=someToggleButton, Path=IsChecked, Converter={StaticResource BoolToVisibilityConverter}}"> 
     <Button /> 
     <Grid /> 
     <TextBox /> 
     <CheckBox /> 
    </StackPanel> 
</StackPanel> 

Trên thực tế, hôm nay tôi sẽ làm điều này với VSM - có một nhà nước với các yếu tố có thể nhìn thấy và một nhà nước với họ không thể nhìn thấy, sau đó sử dụng hai Hành vi GoToState vào nút Toggle để thiết lập nhà nước dựa trên trạng thái chuyển đổi của nút.

+1

Điểm tốt, tuy nhiên mã này chỉ được tạo ra để chứng minh mong muốn tái sử dụng các ràng buộc nói chung. Người ta có thể nhận thức các trường hợp mà các phần tử bị ràng buộc không được đặt gọn gàng như các đồng nghiệp trong một thùng chứa duy nhất. – jpierson

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