2011-12-30 32 views
10

Im cố gắng liên kết 2 điều khiển WPF khác nhau với cùng một thuộc tính trong ViewModel, một CheckBox.IsChecked và Expander.IsExpanded. Các hành vi tôi muốn đạt được là có CheckBox ảnh hưởng đến ViewModel (và do đó Expander là tốt), nhưng không phải là cách khác bị ràng buộc. Cái gì như:WPF One Way Binding bị hỏng

Checkbox Checked -> ViewModel property set to frue -> Expander.Expand 
Checkbox Unchecked -> ViewModel property set to false -> Expander.Collapse 
Expander Expanded -> Nothing else affected 
Expander Collapsed -> Nothing else affected 

Đây là XAML:

<Window x:Class="WpfApplication9.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="MainWindow" Height="350" Width="525"> 
    <Expander IsExpanded="{Binding IsChecked, Mode=OneWay}"> 
     <Expander.Header> 
      <CheckBox IsChecked="{Binding IsChecked}" Content="Is Checked"/> 
     </Expander.Header> 
     <TextBlock Text="Expanded!"/> 
    </Expander> 
</Window> 

và Bộ luật:

using System.ComponentModel; 
using System.Windows; 

namespace WpfApplication9 
{ 
    /// <summary> 
    /// Interaction logic for MainWindow.xaml 
    /// </summary> 
    public partial class MainWindow : Window 
    { 
     public MainWindow() 
     { 
      InitializeComponent(); 
      DataContext = new ViewModel(); 
     } 
    } 

    public class ViewModel: INotifyPropertyChanged 
    { 
     private bool _isChecked; 
     public bool IsChecked 
     { 
      get { return _isChecked; } 
      set 
      { 
       _isChecked = value; 
       NotifyPropertyChange("IsChecked"); 
      } 
     } 

     protected void NotifyPropertyChange(string PropertyName) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(PropertyName)); 
     } 

     public event PropertyChangedEventHandler PropertyChanged = delegate { }; 
    } 
} 

Bây giờ vấn đề của tôi là, ngay sau khi tôi bấm vào Expander để mở rộng/thu hẹp nó, ràng buộc dường như ngừng hoạt động. Bất cứ ai có thể giải thích cho tôi tại sao điều này xảy ra và làm cách nào để tôi đạt được điều này? Cảm ơn trước!

Trả lời

10

mới trả lời

phát hiện bạn có thể làm điều này bằng cách thiết lập của bạn UpdateSourceTrigger để Explicit trên Expander của bạn. Điều này giữ cho ràng buộc là hai chiều, nhưng không bao giờ cập nhật Nguồn vì bạn đang yêu cầu nó không cập nhật nguồn trừ khi bạn nói rõ ràng.

<Expander IsExpanded="{Binding IsChecked, UpdateSourceTrigger=Explicit}"> 
    <Expander.Header> 
     <CheckBox IsChecked="{Binding IsChecked}" Content="Is Checked"/> 
    </Expander.Header> 
    <TextBlock Text="Expanded!"/> 
</Expander> 

Rời câu trả lời cũ của tôi dưới đây để những ý kiến ​​có ý nghĩa, và vì tôi vẫn cảm thấy không có vấn đề với quan điểm cụ thể đang xảy ra trong code-behind của một cái nhìn :)


Câu trả lời cũ

Cá nhân vì đây là mã View-Specific, tôi thấy không có vấn đề với việc sử dụng một sự kiện ClickBox để đặt giá trị IsExpanded của Expander.

private void MyCheckBox_Click(object sender, RoutedEventArgs e) 
{ 
    MyExpander.IsExpanded = ((CheckBox)sender).IsChecked.GetValueOrDefault(); 
} 

Bạn có thể thực hiện việc này thậm chí chung chung hơn bằng cách xóa tên và điều hướng Visual Tree để tìm Expander được liên kết với CheckBox. Dưới đây là một ví dụ sử dụng một số Visual Tree Helpers I built

private void CheckBox_Click(object sender, RoutedEventArgs e) 
{ 
    var chk = (CheckBox)sender; 
    var expander = VisualTreeHelpers.FindAncestor<Expander>(chk); 

    if (expander != null) 
     expander.IsExpanded = chk.IsChecked.GetValueOrDefault(); 
} 
+0

Im tạo chế độ xem với ít nhất 6 Trình tăng thể có Hộp kiểm trên tiêu đề của chúng. Mã quá nhiều của nó và tôi không muốn sử dụng bất kỳ mã nào vì nó làm giảm tính linh hoạt của chế độ xem. –

+0

@HighCore Nếu bạn có nhiều Vùng mở rộng/Hộp kiểm, bạn có thể có kiểu mặc định cho chúng và có thể đặt sự kiện Nhấp làm EventSetter theo kiểu. Tôi sẽ sử dụng một cái gì đó để điều hướng cây thị giác để tìm Expander liên kết với CheckBox đó và bạn sẽ không cần phải sử dụng các giá trị được đặt tên ở tất cả. – Rachel

+0

@HighCore Xem câu trả lời cập nhật của tôi. Nó hoạt động mà không có bất kỳ mã-đằng sau – Rachel

1

Nếu bạn muốn hộp kiểm để ảnh hưởng đến sự giãn nở (nhưng không phải ngược lại) sau đó ràng buộc giãn nở bình thường và sử dụng OneWayToSource vào hộp kiểm:

<Window x:Class="WpfApplication9.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="MainWindow" Height="350" Width="525"> 
    <Expander IsExpanded="{Binding IsChecked}"> 
     <Expander.Header> 
     <CheckBox IsChecked="{Binding IsChecked, Mode=OneWayToSource}" Content="Is Checked"/> 
     </Expander.Header> 
     <TextBlock Text="Expanded!"/> 
    </Expander> 
</Window> 

Sử dụng OneWayToSource vào hộp kiểm sẽ cho phép nó:

  • sửa đổi thuộc tính cơ bản (và do đó ảnh hưởng đến thiết bị mở rộng, cũng bị ràng buộc với thuộc tính đó)
  • không bị ảnh hưởng bởi các thành phần khác thực hiện thay đổi o tài sản tiềm ẩn
+1

tôi không thể làm điều này vì hộp kiểm là biểu diễn dữ liệu chính ở đây.Nó luôn luôn nên phản ánh giá trị trong ViewModel. –

+0

@HighCore Tôi đã chuẩn bị +1 điều này cho đến khi tôi nghĩ về điều đó, vì vậy tôi nghĩ rằng tôi sẽ đợi. Giải pháp tốt đẹp mặc dù nếu điều đó là không cần thiết. – Rachel

+1

Theo MSDN, chế độ mặc định cho các hộp kiểm thường là TwoWay, nhưng bạn đã thử viết nó một cách rõ ràng chưa? "{Binding IsChecked, Mode = TwoWay}" –

1

Nếu bạn muốn tránh bất kỳ mã-đằng sau, bạn có thể thêm một mức độ tách biệt giữa ExpanderCheckBox bang trong ViewModel của bạn:

  private bool _isChecked; 
      public bool IsChecked 
      { 
       get { return _isChecked; } 
       set 
       { 
        _isChecked = value; 
        NotifyPropertyChange("IsChecked"); 
        IsExpanded = value; 
       } 
      } 

      private bool _isExpanded; 
      public bool IsExpanded 
      { 
       get { return _isExpanded; } 
       set 
       { 
        _isExpanded = value; 
        NotifyPropertyChange("IsExpanded"); 
       } 
      } 

    <Expander IsExpanded="{Binding IsExpanded}"> 
     <Expander.Header> 
      <CheckBox IsChecked="{Binding IsChecked}" Content="Is Checked" x:Name="cb"/> 
     </Expander.Header> 
     <TextBlock Text="Expanded!"/> 
    </Expander> 
+0

Vâng, tôi nghĩ đây là phương sách cuối cùng. –