Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么我的WPF项目中的datacontext可以从代码隐藏而不是xaml正常工作?_C#_Wpf_Xaml_Mvvm - Fatal编程技术网

C# 为什么我的WPF项目中的datacontext可以从代码隐藏而不是xaml正常工作?

C# 为什么我的WPF项目中的datacontext可以从代码隐藏而不是xaml正常工作?,c#,wpf,xaml,mvvm,C#,Wpf,Xaml,Mvvm,我一直在做一个小样本Wpf Mvvm项目,用于试验INotifyPropertyChanged接口。该项目实际上工作正常,但我遇到的问题是,只有在MainWindow.xaml的代码隐藏中设置DataContext,该项目才能正常工作。如果我试图在xaml标记中设置DataContext,那么项目的一些功能就不起作用。UI包含一个textblock、textbox(用于输入要在textblock OnPropertyChanged中显示的文本)和submit按钮(除了提供一个使textbox失去

我一直在做一个小样本Wpf Mvvm项目,用于试验INotifyPropertyChanged接口。该项目实际上工作正常,但我遇到的问题是,只有在MainWindow.xaml的代码隐藏中设置DataContext,该项目才能正常工作。如果我试图在xaml标记中设置DataContext,那么项目的一些功能就不起作用。UI包含一个textblock、textbox(用于输入要在textblock OnPropertyChanged中显示的文本)和submit按钮(除了提供一个使textbox失去焦点的位置外,它实际上什么都不做)以及3个用于更改UI背景色的其他按钮(颜色按钮)。UI的默认颜色为橙色——直到通过单击任何颜色按钮更改颜色为止

有3个视图模型,PersonViewModel(文本框绑定到它)、BackgroundViewModel(用于颜色按钮)和一个MainViewModel,它结合了其他两个视图模型。viewModels位于项目的viewModels文件夹中。还有一个ObserveObject类(基本上是ViewModelBase类),它实现INotifyPropertyChanged接口,并由PersonViewModel和BackgroundViewModel继承。ObservableObject.cs位于项目的根文件夹中

这个项目不是纯粹的Mvvm。颜色按钮在MainWindow.xaml的代码隐藏中使用单击事件。如果我在MainWindow.xaml的代码隐藏中设置了DataContext,那么一切都正常工作。如果我在xaml标记中设置DataContext——textbox/textblock功能可以工作,但是颜色按钮不会改变UI的背景色。当我一步一步地浏览代码时,它会正确地浏览所有代码,但UI背景颜色不会改变。我猜这是一个有约束力的东西

可以下载示例项目

代码如下。如果我在xaml标记中设置DataContext,如何使该项目正常运行?我在网格上尝试了以下绑定,它将为UI设置默认的橙色,但颜色按钮不起作用:

<Grid Background="{Binding Background.Color}" DataContext="{StaticResource bc}">
--PersonViewModel.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace NotifyChangeExample.ViewModels
{
    public class PersonViewModel : ObservableObject
    {
        private string _name;

        public string Name
        {
            get
            {
                if (string.IsNullOrEmpty(_name))
                    return "Unknown";
                return _name;
            }
            set
            {
                _name = value;
                OnPropertyChanged("Name");
            }
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media;

namespace NotifyChangeExample.ViewModels
{
    public class BackgroundViewModel : ObservableObject
    {
        private Brush _color;

        public Brush Color
        {
            get
            {
                if (_color == null)
                    return Brushes.Orange;
                return _color;
            }
            set
            {
                _color = value;
                OnPropertyChanged("Color");
            }
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media;

namespace NotifyChangeExample.ViewModels
{
    public class MainViewModel
    {
        public PersonViewModel Person { get; private set; }
        public BackgroundViewModel Background { get; private set; }

        public MainViewModel()
        {
            Person = new PersonViewModel();
            Background = new BackgroundViewModel();      
        }

        public void SetBackground(Brush brushColor)
        {
            Background.Color = brushColor;
        }
    }
}
--BackgroundViewModel.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace NotifyChangeExample.ViewModels
{
    public class PersonViewModel : ObservableObject
    {
        private string _name;

        public string Name
        {
            get
            {
                if (string.IsNullOrEmpty(_name))
                    return "Unknown";
                return _name;
            }
            set
            {
                _name = value;
                OnPropertyChanged("Name");
            }
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media;

namespace NotifyChangeExample.ViewModels
{
    public class BackgroundViewModel : ObservableObject
    {
        private Brush _color;

        public Brush Color
        {
            get
            {
                if (_color == null)
                    return Brushes.Orange;
                return _color;
            }
            set
            {
                _color = value;
                OnPropertyChanged("Color");
            }
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media;

namespace NotifyChangeExample.ViewModels
{
    public class MainViewModel
    {
        public PersonViewModel Person { get; private set; }
        public BackgroundViewModel Background { get; private set; }

        public MainViewModel()
        {
            Person = new PersonViewModel();
            Background = new BackgroundViewModel();      
        }

        public void SetBackground(Brush brushColor)
        {
            Background.Color = brushColor;
        }
    }
}
--MainViewModel.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace NotifyChangeExample.ViewModels
{
    public class PersonViewModel : ObservableObject
    {
        private string _name;

        public string Name
        {
            get
            {
                if (string.IsNullOrEmpty(_name))
                    return "Unknown";
                return _name;
            }
            set
            {
                _name = value;
                OnPropertyChanged("Name");
            }
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media;

namespace NotifyChangeExample.ViewModels
{
    public class BackgroundViewModel : ObservableObject
    {
        private Brush _color;

        public Brush Color
        {
            get
            {
                if (_color == null)
                    return Brushes.Orange;
                return _color;
            }
            set
            {
                _color = value;
                OnPropertyChanged("Color");
            }
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media;

namespace NotifyChangeExample.ViewModels
{
    public class MainViewModel
    {
        public PersonViewModel Person { get; private set; }
        public BackgroundViewModel Background { get; private set; }

        public MainViewModel()
        {
            Person = new PersonViewModel();
            Background = new BackgroundViewModel();      
        }

        public void SetBackground(Brush brushColor)
        {
            Background.Color = brushColor;
        }
    }
}

当您从XAML绑定ViewModel时,它无法工作,因为在后面的代码中,您正在为本地ViewModel“\u main”设置颜色。但是_main没有绑定到视图,bc是。

当您从XAML绑定ViewModel时,它无法工作,因为在后面的代码中,您正在为本地ViewModel“_main”设置颜色。但是_main没有绑定到视图,bc是。

您的后台代码使用的是_main对象,因此如果您想在XAML中设置DataContext,只需要使用DataContext设置_main即可

因此,在XAML中,您将

<Window.DataContext>        
    <VM:MainViewModel />
</Window.DataContext>

或者,从XAML中删除DataContext,并使用此主窗口构造函数:

private readonly MainViewModel _main = new MainViewModel();

public MainWindow()
{
    InitializeComponent();
    DataContext = _main;
}

您的代码隐藏正在使用_main对象,因此如果您想在XAML中设置DataContext,只需使用DataContext设置_main即可

因此,在XAML中,您将

<Window.DataContext>        
    <VM:MainViewModel />
</Window.DataContext>

或者,从XAML中删除DataContext,并使用此主窗口构造函数:

private readonly MainViewModel _main = new MainViewModel();

public MainWindow()
{
    InitializeComponent();
    DataContext = _main;
}

使用
可以创建2个MainViewModel对象。当前,即使您将“bc”设置为DataContext,按钮始终与在代码隐藏中创建的按钮一起工作。请参见此处:。虽然问题听起来完全不同,但我即将以重复的方式结束此操作。如果您真的想了解MVVM,您应该将这些单击事件从代码隐藏中移开,并将其转换为viewmodel上的
ICommand
实现。我计划在此项目中使用ICommand作为MVVM中的练习。在继续下一个示例实现之前,我只想确保我没有遗漏对DataContext的任何理解。谢谢大家的回复。建议的stackoverflow.com/a/34617048/1136211链接有我想要的解决方案——我可以在xaml中设置datacontext,然后在代码中声明_main,如下所示--_main=(MainViewModel)datacontext;现在我的示例项目工作了!使用
可以创建2个MainViewModel对象。当前,即使您将“bc”设置为DataContext,按钮始终与在代码隐藏中创建的按钮一起工作。请参见此处:。虽然问题听起来完全不同,但我即将以重复的方式结束此操作。如果您真的想了解MVVM,您应该将这些单击事件从代码隐藏中移开,并将其转换为viewmodel上的
ICommand
实现。我计划在此项目中使用ICommand作为MVVM中的练习。在继续下一个示例实现之前,我只想确保我没有遗漏对DataContext的任何理解。谢谢大家的回复。建议的stackoverflow.com/a/34617048/1136211链接有我想要的解决方案——我可以在xaml中设置datacontext,然后在代码中声明_main,如下所示--_main=(MainViewModel)datacontext;现在我的示例项目工作了!我想我的问题是——在我当前的设置中,有没有办法将main绑定到视图?或者代码隐藏是这个设置的唯一方法吗?试试Marc的回答。我想我的问题是——在我当前的设置中,有没有一种方法可以将_main绑定到视图?或者代码隐藏是这个设置的唯一方法吗?试试Marc的答案。我稍微更新了答案。如果在XAML中设置DataContext,则不需要在代码隐藏中更新MainViewModel。我稍微更新了答案。如果在XAML中设置DataContext,则不需要在代码隐藏中新建MainViewModel。