2014-02-12 99 views
0

財產BindingExpression路徑錯誤我有以下的知名度綁定拋出:在視圖模型

System.Windows.Data Error: 40 : BindingExpression path error: 'Vis' property not found on 'object' ''LoginViewModel' (HashCode=22943289)'. BindingExpression:Path=Vis; DataItem='LoginViewModel' (HashCode=22943289); target element is 'Login' (Name=''); target property is 'Visibility' (type 'Visibility')

不能看到我做了什麼錯,但屬性確實在MainViewModel存在。也許我正在展示和隱藏這個錯誤的方式。

<Window x:Class="Bt.MainWindow" 
     xmlns:vm="clr-namespace:Bt" 
     xmlns:ctrls="clr-namespace:Bt.Controls"> 

    <Window.DataContext> 
     <vm:MainViewModel x:Name="MWin" /> 
    </Window.DataContext> 

    <Grid> 
     <ctrls:Login Visibility="{Binding Vis}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"></ctrls:Login> 
    </Grid> 
</Window> 

視圖模型:

namespace Bt 
{ 
    class MainViewModel : INotifyPropertyChanged 
    { 
     public MainViewModel() 
     { 
      Vis = "Collapsed"; 
     } 

     private string _vis = "Collapsed"; 
     public string Vis 
     { 
      get { return _vis; } 
      set 
      { 
        _vis = value; 
        RaisePropertyChanged("Vis"); 
      } 
     } 
    } 
} 


[編輯]捕獲用戶控制內,當用戶控制的可見性在主窗口中被改變。

我意識到轉換器沒有被正確調用,所以可能還需要一些幫助。至於其他希望你可以看到我想要實現的。

查看:

<UserControl x:Class="Bt.Controls.Login" 
      xmlns:app="clr-namespace:Bt" 
      xmlns:viewmodel="clr-namespace:Bt.Controls" 
      mc:Ignorable="d" 
      Visibility="{Binding Visi,Converter={StaticResource BooleanToVisibilityConverter}}" 
      > 
</UserControl> 

視圖模型:

namespace Bt.Controls 
{ 
    class LoginViewModel : INotifyPropertyChanged 
    { 
     public LoginViewModel(){} 

     private bool _visi = true; 
     public bool Visi 
     { 
      get { return _visi; } 
      set 
      { 
       _visi = value; 
       RaisePropertyChanged("Visi"); 
       MessageBox.Show("Visi set"); 
       reset_timer(_visi); 
      } 
     } 
    } 

    [ValueConversion(typeof(bool), typeof(Visibility))] 
    public class VisibilityConverter : IValueConverter 
    { 
     public const string Invert = "Invert"; 

     #region IValueConverter Members 

     public object Convert(object value, Type targetType, object parameter, 
      System.Globalization.CultureInfo culture) 
     { 
      if (targetType != typeof(Visibility)) 
       throw new InvalidOperationException("The target must be a Visibility."); 

      bool? bValue = (bool?)value; 

      if (parameter != null && parameter as string == Invert) 
       bValue = !bValue; 

      return bValue.HasValue && bValue.Value ? Visibility.Visible : Visibility.Collapsed; 
     } 

     public object ConvertBack(object value, Type targetType, object parameter, 
      System.Globalization.CultureInfo culture) 
     { 
      return ((value is Visibility) && (((Visibility)value) == Visibility.Visible)); 
     } 
     #endregion 
    } 
} 

回答

2

由於顯而易見的錯誤BindingEngine在LoginViewModel尋找財產Vis而不是在MainViewModel。 (您必須將登錄用戶控件的DataContext設置爲LoginViewModel)。

您需要得到窗口的DataContext的,你可以開始使用RelativeSource

<ctrls:Login Visibility="{Binding DataContext.Vis, 
     RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}"/> 

你也應該創建Visbool並在結合使用BooleanToVisibility轉換器。

<Grid> 
    <Grid.Resources> 
     <BooleanToVisibilityConverter x:Key="BooelanToVisibilityConverter"/> 
    </Grid.Resources> 
    <ctrls:Login Visibility="{Binding DataContext.Vis, 
          RelativeSource={RelativeSource Mode=FindAncestor, 
                  AncestorType=Window}}", 
         Converter={StaticResource BooelanToVisibilityConverter} 
       HorizontalAlignment="Stretch" 
       VerticalAlignment="Stretch"/> 
</Grid> 

我會勸阻使用視圖模型Visibility財產的,因爲它是瀏覽件事不應該出現在視圖模型。有布爾是完全好的,你可以隨時使用轉換器轉換。

+0

只是對此的擴展。在ctrls:Login ViewModel中,我想捕獲它變得可見的時候,我試圖將UserControl的View Visibility綁定到ViewModel中的一個屬性,但是當測試如果設置爲主窗口中的Visible時,它不會被反射messagebox我已經放置在屬性更改處理程序。爲了清晰起見,我將添加上面的代碼。 – Hank

0

保持Vis類型的Visibility

class MainViewModel : INotifyPropertyChanged 
{ 
    public MainViewModel() 
    { 

    } 

    private Visibility _vis = Visibility.Collapsed; 
    public Visibility Vis 
    { 
     get { return _vis; } 
     set 
     { 
      _vis = value; 
      RaisePropertyChanged("Vis"); 
     } 
    } 
} 

而且註明來源爲綁定,

<Window x:Class="Bt.MainWindow" 
    xmlns:vm="clr-namespace:Bt" 
    xmlns:ctrls="clr-namespace:Bt.Controls"> 

    <Window.Resources> 
     <vm:MainViewModel x:Key="MWin" />   
    </Window.Resources> 

    <Grid> 
     <ctrls:Login Visibility="{Binding Vis, RelativeSource={StaticResource MWin}}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"></ctrls:Login> 
    </Grid> 
</Window> 

隨着羅希特說,你可以使用BooleanToVisibility,而不是更改屬性爲Visibility的..