Error de ruta de BindingExpression para la propiedad en ViewModel
Frecuentes
Visto 2,216 equipos
2
I have the below visibility binding that is throwing:
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')
Can't see what I've done wrong, the property does exist in the MainViewModel. Maybe I'm going about showing and hiding this the wrong way.
<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>
Ver modelo:
namespace Bt
{
class MainViewModel : INotifyPropertyChanged
{
public MainViewModel()
{
Vis = "Collapsed";
}
private string _vis = "Collapsed";
public string Vis
{
get { return _vis; }
set
{
_vis = value;
RaisePropertyChanged("Vis");
}
}
}
}
[EDITAR] Capturing inside the User Control, when the User Control's visibility is changed in the Main window.
I realize that the converter is not being called correctly, so may need some help there as well. As for the rest hopefully you can see what I'm trying to achieve.
Vista
<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>
Ver modelo:
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 Respuestas
3
As evident from error BindingEngine is looking for property Vis
in LoginViewModel
y no en MainViewModel
. (You must have set DataContext
for your Login UserControl to LoginViewModel
).
Tu necesitas get Window's DataContext que puedes obtener usando RelativeSource
:
<ctrls:Login Visibility="{Binding DataContext.Vis,
RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}"/>
Also you should create Vis
as bool
y use BooleanToVisibility
converter in your binding.
<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>
Lo haría discourage use of Visibility
property in ViewModel because it's View thing which should not be there in ViewModel. Having bool is perfectly fine which you can always convert using converter.
Respondido 12 Feb 14, 07:02
0
Guardar Vis
como tipo de Visibility
class MainViewModel : INotifyPropertyChanged
{
public MainViewModel()
{
}
private Visibility _vis = Visibility.Collapsed;
public Visibility Vis
{
get { return _vis; }
set
{
_vis = value;
RaisePropertyChanged("Vis");
}
}
}
Also specify the Source for the binding,
<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>
As Rohit says, you could use BooleanToVisibility
instead of changing the property as Visibility
..
Respondido 12 Feb 14, 07:02
No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas c# wpf xaml binding or haz tu propia pregunta.
just an extension to this. In the ctrls:Login ViewModel, I wanted to capture when it becomes visible, I have tried binding the UserControl's View Visibility to a property in the ViewModel, however when testing if set to Visible in the main window it doesn't get reflect by a messagebox I have placed in the property changed handler. I will add the code above for clarity. - Hank