2009-09-18 29 views
6

Tôi có Markup này:WPF MultiBinding Fails. Tại sao?

<GroupBox BorderThickness="2"> 
    <GroupBox.BorderBrush> 
     <SolidColorBrush x:Name="Border"> 
      <SolidColorBrush.Color> 
       <MultiBinding Converter="{StaticResource ConnectionAndLoggedInToBorderBrush}"> 
        <Binding Path="IsConnected"/> 
        <Binding Path="IsLoggedIn"/> 
       </MultiBinding> 
      </SolidColorBrush.Color> 
     </SolidColorBrush> 
    </GroupBox.BorderBrush> 

Trong đoạn mã đằng sau tôi có dòng này trong phương pháp Window_Loaded:

DataContext = uiManager; 

uiManager là loại UIManager có hai thuộc tính công cộng được đặt tên IsConnected và IsLoggedIn.

Mã này không thành công khi khởi động vì mảng giá trị trong Trình chuyển đổi được gọi bằng cách Ghép nối không được lấp đầy với các toán tử nhưng có giá trị là DependencyProperty.UnsetValue.

Khi tôi sử dụng đánh dấu bên dưới (và thay đổi loại đồng hồ của bộ chuyển đổi) nó hoạt động.

<GroupBox BorderThickness="2"> 
    <GroupBox.BorderBrush> 
     <MultiBinding Converter="{StaticResource ConnectionAndLoggedInToBorderBrush}"> 
       <Binding Path="IsConnected"/> 
       <Binding Path="IsLoggedIn"/> 
     </MultiBinding> 
    </GroupBox.BorderBrush> 

Dường như tập hợp ràng buộc thông qua DataContext trong mã phía sau không thành công trong ví dụ đầu tiên, nhưng hoạt động trong ví dụ thứ hai. Tại sao?

Đối với đầy đủ bên dưới lớp UIManager:

public class UIManager:IUIManager 
    { 

     #region Implementation of IUIManager 

     private const string IsLoggedInProperty = "IsLoggedIn"; 
     private bool loggedIn; 
     private readonly object loggedInLock = new object(); 
     public bool IsLoggedIn 
     { 
      get 
      { 
       lock (loggedInLock) 
       { 
        return loggedIn; 
       } 
      } 
      set 
      { 
       lock (loggedInLock) 
       { 
        if(value==loggedIn)return; 
        loggedIn = value; 
        OnPropertyChanged(IsLoggedInProperty); 
       } 
      } 
     } 

     private void OnPropertyChanged(string property) 
     { 
      if(PropertyChanged!=null)PropertyChanged(this,new PropertyChangedEventArgs(property)); 
     } 

     private const string IsConnectedProperty = "IsConnected"; 
     private bool isConnected; 
     private object isConnectedLock = new object(); 
     public bool IsConnected 
     { 
      get 
      { 
       lock (isConnectedLock) 
       { 
        return isConnected; 
       } 
      } 
      set 
      { 
       lock (isConnectedLock) 
       { 
        if(value==isConnected)return; 
        isConnected = value; 
        OnPropertyChanged(IsConnectedProperty); 
       } 
      } 
     } 

     #endregion 

     #region Implementation of INotifyPropertyChanged 

     public event PropertyChangedEventHandler PropertyChanged; 

     #endregion 
    } 

EDIT: Phương pháp chuyển đổi cho XAML không (nó không thành công về việc chuyển đổi để bool các giá trị [0]:

public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) 
     { 
      var is_connected = (bool) values[0]; 
      var is_loggedin = (bool) values[1]; 
      return is_loggedin 
         ? is_connected 
          ? Colors.YellowGreen 
          : Colors.Red 
         : Colors.Gray; 
     } 

cho XAML đang hoạt động:

public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) 
     { 
      var is_connected = (bool) values[0]; 
      var is_loggedin = (bool) values[1]; 
      return is_loggedin 
         ? is_connected 
          ? Brushes.YellowGreen 
          : Brushes.Red 
         : Brushes.Gray; 
     } 
+0

Bạn có thể đính kèm mã cho trình chuyển đổi của mình không? Có gì sai khi đặt GroupBox thành Brush thay vì thuộc tính SolidColorBrush.Color? – bendewey

+0

Tôi đã thêm phương thức chuyển đổi. Tôi cần để lộ các tài sản màu sắc để có thể thực hiện một ColorAninmation. Điều này trong chính nó làm việc với XAML đầu tiên khi tôi loại bỏ MultiBinding. – Dabblernl

Trả lời

15

Sự cố không liên quan gì đến MultiBinding hoặc trình chuyển đổi của bạn. DependencyProperty.UnsetValue có nghĩa là ràng buộc không có giá trị. Và quả thực nếu bạn chạy trong chế độ gỡ lỗi bạn có thể thấy lỗi ràng buộc trong Output cửa sổ:

System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=IsConnected; DataItem=null; target element is 'SolidColorBrush' (HashCode=17654054); target property is 'Color' (type 'Color') 
System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=IsLoggedIn; DataItem=null; target element is 'SolidColorBrush' (HashCode=17654054); target property is 'Color' (type 'Color') 

Vì vậy, hãy đơn giản hóa việc đánh dấu một chút và áp dụng một số chẩn đoán:

<GroupBox> 
    <GroupBox.BorderBrush> 
     <SolidColorBrush> 
      <SolidColorBrush.Color> 
       <Binding Path="GroupColor" PresentationTraceSources.TraceLevel="High"/> 
      </SolidColorBrush.Color> 
     </SolidColorBrush> 
    </GroupBox.BorderBrush> 
</GroupBox> 

Áp dụng kèm theo tài sản PresentationTraceSources.TraceLevel phụ thuộc sản lượng thêm một số đầu ra:

System.Windows.Data Warning: 52 : Created BindingExpression (hash=17654054) for Binding (hash=44624228) 
System.Windows.Data Warning: 54 : Path: 'GroupColor' 
System.Windows.Data Warning: 56 : BindingExpression (hash=17654054): Default mode resolved to OneWay 
System.Windows.Data Warning: 57 : BindingExpression (hash=17654054): Default update trigger resolved to PropertyChanged 
System.Windows.Data Warning: 58 : BindingExpression (hash=17654054): Attach to System.Windows.Media.SolidColorBrush.Color (hash=52727599) 
System.Windows.Data Warning: 60 : BindingExpression (hash=17654054): Use Framework mentor <null> 
System.Windows.Data Warning: 63 : BindingExpression (hash=17654054): Resolving source 
System.Windows.Data Warning: 65 : BindingExpression (hash=17654054): Framework mentor not found 
System.Windows.Data Warning: 61 : BindingExpression (hash=17654054): Resolve source deferred 
System.Windows.Data Warning: 91 : BindingExpression (hash=17654054): Got InheritanceContextChanged event from SolidColorBrush (hash=52727599) 
System.Windows.Data Warning: 63 : BindingExpression (hash=17654054): Resolving source 
System.Windows.Data Warning: 66 : BindingExpression (hash=17654054): Found data context element: GroupBox (hash=51393439) (OK) 
System.Windows.Data Warning: 67 : BindingExpression (hash=17654054): DataContext is null 
System.Windows.Data Warning: 91 : BindingExpression (hash=17654054): Got InheritanceContextChanged event from SolidColorBrush (hash=52727599) 
System.Windows.Data Warning: 63 : BindingExpression (hash=17654054): Resolving source 
System.Windows.Data Warning: 65 : BindingExpression (hash=17654054): Framework mentor not found 
System.Windows.Data Warning: 63 : BindingExpression (hash=17654054): Resolving source 
System.Windows.Data Warning: 65 : BindingExpression (hash=17654054): Framework mentor not found 
System.Windows.Data Warning: 63 : BindingExpression (hash=17654054): Resolving source (last chance) 
System.Windows.Data Warning: 65 : BindingExpression (hash=17654054): Framework mentor not found 
System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=GroupColor; DataItem=null; target element is 'SolidColorBrush' (HashCode=52727599); target property is 'Color' (type 'Color') 

Chúng tôi thấy rằng ràng buộc không tìm thấy DataContext và ràng buộc không thành công. Khi tôi thay đổi nhà xây dựng của cửa sổ để DataContext được thiết lập trước khi khởi tạo nội dung các tác phẩm ràng buộc:

public Window1() 
{ 
    DataContext = ...; 
    InitializeComponent(); 
} 

Đó là lạ vì đối với các ràng buộc ở những nơi khác điều này không thành vấn đề. Không chắc chắn tại sao nó không hoạt động ở đó vì vậy tôi chỉ có thể cung cấp cách giải quyết. Điều gì làm việc ví dụ như là tạo bàn chải như một nguồn lực với các ràng buộc (tài nguyên đó cũng có thể là địa phương để các GroupBox):

<GroupBox BorderBrush="{DynamicResource resbrush}"> 
    <GroupBox.Resources> 
     <SolidColorBrush x:Key="resbrush"> 
      <SolidColorBrush.Color> 
       <MultiBinding Converter="{StaticResource ConnectionAndLoggedInToBorderBrush}"> 
        <Binding Path="IsConnected"/> 
        <Binding Path="IsLoggedIn"/> 
       </MultiBinding> 
      </SolidColorBrush.Color> 
     </SolidColorBrush> 
    </GroupBox.Resources> 
</GroupBox> 

tôi sẽ đề nghị mặc dù để thả các MultiBinding và làm một số tiền xử lý trong DataContext nếu lớp học UIManager của bạn là một số loại MVVMViewModel.

+0

Kudo, thiết lập DataContext trong hàm tạo trong đoạn mã phía sau đã làm thủ thuật. – Dabblernl

0

Đó là vì những lý do như thế này mà bạn có thể muốn xem xét việc học MVVM. Mô hình này giúp bạn trừu tượng hóa mô hình và các ràng buộc để bạn không phải dựa quá nhiều vào các DP - bạn có thể chỉ cần liên kết với một thuộc tính đáng chú ý trong một mô hình khung nhìn thay thế.

Có một số bài viết xuất sắc về MVVM, vì vậy tôi khuyên bạn nên bắt đầu bằng cách đọc các tác phẩm của Karl Shifflett, Josh Smith, Marlon Grech và Sacha Barber.

+2

Anh ấy đã liên kết với một lớp INotifyPropertyChanged. – gix

1

Lý thuyết của tôi. Màu là struct (không thể rỗng), vì vậy SolidColorBrush.Color = null là sai. WPF không thể tạo SolidColorBrush, và bạn nhận được ngoại lệ.

<GroupBox.BorderBrush> 
    <SolidColorBrush x:Name="Border"> 
     <SolidColorBrush.Color> 
      <MultiBinding Converter="{StaticResource 
          ConnectionAndLoggedInToBorderBrush}"> 
       <Binding Path="IsConnected"/> 
       <Binding Path="IsLoggedIn"/> 
      </MultiBinding> 
     </SolidColorBrush.Color> 
    </SolidColorBrush> 
</GroupBox.BorderBrush> 

BorderBrush là đối tượng (có thể rỗng), do đó GroupBox.BorderBrush = null là OK.

<GroupBox.BorderBrush> 
     <MultiBinding Converter="{StaticResource 
        ConnectionAndLoggedInToBorderBrush}"> 
      <Binding Path="IsConnected"/> 
      <Binding Path="IsLoggedIn"/> 
     </MultiBinding> 
</GroupBox.BorderBrush> 

SolidColorBrush này không phải là đối tượng mà là NHÀ MÁY. Nó được khởi tạo chỉ khi cần thiết, và tại thời điểm đó bạn đã có DataContext đính kèm.

<GroupBox.Resources> 
     <SolidColorBrush x:Key="resbrush"> 
      <SolidColorBrush.Color> 
       <MultiBinding Converter="{StaticResource 
           ConnectionAndLoggedInToBorderBrush}"> 
        <Binding Path="IsConnected"/> 
        <Binding Path="IsLoggedIn"/> 
       </MultiBinding> 
      </SolidColorBrush.Color> 
     </SolidColorBrush> 
</GroupBox.Resources> 

Chỉ 2 xu của tôi.

Đọc bài viết của tôi, btw, có thể hữu ích nếu bạn cần một số Bindings lạ hoặc Ảnh động với Trình chuyển đổi kỳ lạ. http://www.codeproject.com/KB/WPF/BindingHub.aspx

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