C# 控件可见性与ViewModel属性的绑定不存在';行不通

C# 控件可见性与ViewModel属性的绑定不存在';行不通,c#,wpf,xaml,mvvm,C#,Wpf,Xaml,Mvvm,我正在将一个相当大的WPF应用程序从三层转换为MVVM,并正在学习MVVM。到目前为止,我还没有深入研究绑定(等)的太多细节,所以请耐心听我说 我正在尝试将多个控件的System.Windows.Visibility绑定到ViewModel的公共属性(“状态”)。加载父选项卡项时,将根据需要读取和处理State属性。但是,在对特性进行后续更改时,这些更改似乎会被忽略。我(重新)检查了绑定,调试了转换器等等,这让我发疯 视图模型: public class MarketingListViewMod

我正在将一个相当大的WPF应用程序从三层转换为MVVM,并正在学习MVVM。到目前为止,我还没有深入研究绑定(等)的太多细节,所以请耐心听我说

我正在尝试将多个控件的System.Windows.Visibility绑定到ViewModel的公共属性(“状态”)。加载父选项卡项时,将根据需要读取和处理State属性。但是,在对特性进行后续更改时,这些更改似乎会被忽略。我(重新)检查了绑定,调试了转换器等等,这让我发疯

视图模型:

public class MarketingListViewModel: IDisposable, INotifyPropertyChanged
{
    private UiState state;

    public event PropertyChangedEventHandler PropertyChanged;
    public UiState State 
    {
        get { return state; }
        set
        {
            if (state != value)
            {
                state = value;
                NotifyPropertyChanged("State");
            }
        }
    }

    public MarketingListViewModel() 
    {
        State = UiState.View;
    }

    private void NotifyPropertyChanged(String info) 
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(info));
        }
    }

}
视图:

有人知道为什么控件在状态更改后不更新其可见性吗

非常感谢

DPH

编辑--转换器:

[ValueConversion(typeof(WpfCrm.UiState), typeof(System.Windows.Visibility))]
public class EditStateToVisibilityConverter: IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        UiState state = (UiState)value;
        if (state == UiState.View) return Visibility.Collapsed;
        else return Visibility.Visible;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return null;
    }
}

[ValueConversion(typeof(WpfCrm.UiState), typeof(System.Windows.Visibility))]
public class ViewStateToVisibilityConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        UiState state = (UiState)value;
        if (state == UiState.View) return Visibility.Visible;
        else return Visibility.Collapsed;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return null;
    }
}

您似乎使用了视图模型的两个不同实例,一个在XAML中声明和使用

<UserControl.Resources>
    <DPH:MarketingListViewModel x:Key="listVM" />
</UserControl.Resources>
<Grid DataContext="{StaticResource listVM}" >
当然,您应该只使用一个。因此,将您的代码隐藏声明更改为

listVM = (MarketingListViewModel)Resources["listVM"]; 

您似乎使用了视图模型的两个不同实例,一个在XAML中声明和使用

<UserControl.Resources>
    <DPH:MarketingListViewModel x:Key="listVM" />
</UserControl.Resources>
<Grid DataContext="{StaticResource listVM}" >
当然,您应该只使用一个。因此,将您的代码隐藏声明更改为

listVM = (MarketingListViewModel)Resources["listVM"]; 

好的,有一个错误。您将listVM声明为

var listVM = new MarketingListViewModel();
但这不是XAML中的listVM。在XAML中,您创建了MarketingListViewModel的另一个实例。所以,当您尝试更改代码中声明的listVM时,什么也不会发生,因为该对象不是网格的DataContext

在单击处理程序中,必须编写以下内容:

private void buttonEditList_Click(object sender, RoutedEventArgs e) 
{
    var _listVM = (MarketingListViewModel)FindResource("listVM");
    _listVM.State = UiState.Edit;
}
或者将代码隐藏中的listVM声明替换为以下声明:

listVM = (MarketingListViewModel)FindResource("listVM");
这样就不需要更改事件处理程序


希望有帮助。

好的,有个错误。您将listVM声明为

var listVM = new MarketingListViewModel();
但这不是XAML中的listVM。在XAML中,您创建了MarketingListViewModel的另一个实例。所以,当您尝试更改代码中声明的listVM时,什么也不会发生,因为该对象不是网格的DataContext

在单击处理程序中,必须编写以下内容:

private void buttonEditList_Click(object sender, RoutedEventArgs e) 
{
    var _listVM = (MarketingListViewModel)FindResource("listVM");
    _listVM.State = UiState.Edit;
}
或者将代码隐藏中的listVM声明替换为以下声明:

listVM = (MarketingListViewModel)FindResource("listVM");
这样就不需要更改事件处理程序


希望有帮助。

刚刚添加的转换器代码是什么-谢谢!是否在代码隐藏的某个地方声明listVM?是--listVM=new MarketingListViewModel();--在视图构造函数中的InitializeComponent()之后。非常感谢大家!15个小时的头部撞击在10分钟内由SO解决。刚刚添加的转换器代码是什么-谢谢!是否在代码隐藏的某个地方声明listVM?是--listVM=new MarketingListViewModel();--在视图构造函数中的InitializeComponent()之后。非常感谢大家!15个小时的头痛在10分钟内就被SO解决了。我将把这个放在构造函数中,而不是创建一个新的VM@TonyVitabile你的意思是什么?最初的注释是“listVM=new MarketingListViewModel();--就在视图构造函数中InitializeComponent()之后”。我写了“在声明后面更改代码”,所以它显然也在构造函数中。我将把它放在构造函数中,以代替创建新声明的代码VM@TonyVitabile你的意思是什么?最初的注释是“listVM=new MarketingListViewModel();--就在视图构造函数中InitializeComponent()之后”。我写了“更改声明背后的代码”,所以它显然也在构造函数中。