视图模型中属性的绑定表达式路径错误



>我有以下可见性绑定,它正在抛出:

System.Windows.Data 错误: 40: 绑定表达式路径错误: 'Vis' 在"对象"登录视图模型"(哈希代码=22943289)"上找不到属性。 绑定表达式:路径=Vis;DataItem='LoginViewModel' (哈希代码=22943289);目标元素是"登录"(名称=");目标 属性为"可见性"(类型"可见性")

看不到我做错了什么,该属性确实存在于 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
    }
}

从错误中可以明显看出,绑定引擎正在查找LoginViewModel而不是MainViewModel中的属性Vis。(您必须已将登录用户控件的DataContext设置为 LoginViewModel )。

您需要获取Window的数据上下文,您可以使用RelativeSource获取:

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

此外,还应创建Vis作为bool,并在绑定中使用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>

我不鼓励在ViewModel中使用Visibility属性,因为它是View的东西,不应该存在于ViewModel中。拥有布尔值非常好,您可以随时使用转换器进行转换。

保留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>

正如 Rohit 所说,您可以使用BooleanToVisibility而不是Visibility更改属性。

最新更新