C# UserControl WPF中的DataContext绑定

C# UserControl WPF中的DataContext绑定,c#,wpf,xaml,mvvm,datacontext,C#,Wpf,Xaml,Mvvm,Datacontext,正在尝试在UserControl中获取DataContext 我的 我有模型车 using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Runtime.CompilerServices; using System.Text; using System.Threading.Tasks; namespace AutoShop.MVVM.

正在尝试在UserControl中获取DataContext

我的

我有模型车

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;

namespace AutoShop.MVVM.Model
{
    class Car : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        public void OnPropertyChanged([CallerMemberName] string prop = "")
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(prop));
        }


        private string _Model;
        public string Model
        {
            get
            {
                return _Model;
            }
            set
            {
                _Model = value;
                OnPropertyChanged();
            }
        }

        private string _Mark;
        public string Mark
        {
            get
            {
                return _Mark;
            }
            set
            {
                _Mark = value;
                OnPropertyChanged();
            }
        }

        private float _Volume;
        public float Volume
        {
            get
            {
                return _Volume;
            }
            set
            {
                _Volume = value;
                OnPropertyChanged();
            }
        }

        private int _DateOfIssue;
        public int DateOfIssue
        {
            get
            {
                return _DateOfIssue;
            }
            set
            {
                _DateOfIssue = value;
                OnPropertyChanged();
            }
        }

        public enum EngineTypes { 
            DISEL,
            PETROL
        };

        private EngineTypes _EngineType;
        public EngineTypes EngineType
        {
            get
            {
                return _EngineType;
            }
            set
            {
                _EngineType = value;
                OnPropertyChanged();
            }
        }

        private string _ImageUrl;

        public string ImageUrl
        {
            get
            {
                return _ImageUrl;
            }
            set
            {
                _ImageUrl = value;
                OnPropertyChanged();
            }
        }

        public Car()
        {

        }
    }
}
我有主视图模型

using AutoShop.MVVM.Model;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows;

namespace AutoShop.MVVM.ViewModel
{
    class MainViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        public void OnPropertyChanged([CallerMemberName] string prop = "")
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(prop));
        }

        public HomeViewModel HomeVM; 

        private object _CurrentPage;
        public object CurrentPage
        {
            get
            {
                return _CurrentPage;
            }
            set
            {
                _CurrentPage = value;
                OnPropertyChanged();
            }
        }

        private List<Car> _Cars;

        public List<Car> Cars
        {
            get
            {
                return _Cars;
            }
            set
            {
                _Cars = value;
                OnPropertyChanged();
            }
        }

        public MainViewModel()
        {
            Cars = new List<Car>() {
                new Car
                {
                    Mark = "Audi",
                    Model = "asdf",
                    Volume = 1.4F,
                    DateOfIssue = 2019,
                    EngineType = Car.EngineTypes.DISEL,
                    ImageUrl = "img/img"
                },
                new Car
                {
                    Mark = "Moto",
                    Model = "asdf",
                    Volume = 1.4F,
                    DateOfIssue = 2019,
                    EngineType = Car.EngineTypes.DISEL,
                    ImageUrl = "img/img"
                },
                new Car
                {
                    Mark = "Some",
                    Model = "asdf",
                    Volume = 1.4F,
                    DateOfIssue = 2019,
                    EngineType = Car.EngineTypes.DISEL,
                    ImageUrl = "img/img"
                }
            };


            HomeVM = new HomeViewModel();
            CurrentPage = HomeVM;

        }
    }
}
我添加了
ProductPage.xaml

<ContentControl Margin="10" Grid.Column="1" Content="{Binding CurrentPage}"/>

问题是没有输出任何内容,我认为这可能是由于失去了上下文。如何正确地将上下文传递给UserControl(ProductPage.xaml)?

更新:


DataContext正在工作,因为
{Binding CurrentPage}
正在工作,但是Cars字段上的Binding不工作

2.2.2.2找到一个

public MainForm()
{
    InitializeComponent();
    //set the MainForm DataContext
    DataContext = new MainViewModel();
}
3.应添加ContentControl.DataTemplate以显示HomeViewModel

----20210427更新

这里是我制作的演示,项目名称是WpfApp4

MainWindow.xaml

<Window x:Class="WpfApp4.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp4"
        xmlns:views="clr-namespace:WpfApp4.Views"
        xmlns:viewModels="clr-namespace:WpfApp4.ViewModels"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.DataContext>
        <viewModels:MainWindowViewModel/>
    </Window.DataContext>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <ListBox Grid.Column="0" ItemsSource="{Binding ItemsSource, Mode=OneWay}" SelectedItem="{Binding SelectedCarViewModel, Mode=TwoWay}">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Name}"/>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
        <Grid Grid.Column="1">
            <ContentControl Content="{Binding SelectedCarViewModel}">
                <ContentControl.ContentTemplate>
                    <!--Style your product page here-->
                    <DataTemplate DataType="{x:Type viewModels:CarViewModel}">
                        <UniformGrid Columns="2">
                            <TextBlock Text="Name"/>
                            <TextBlock Text="{Binding Name}"/>
                            <TextBlock Text="Volume"/>
                            <TextBlock Text="{Binding Volume}"/>
                            <TextBlock Text="Price"/>
                            <TextBlock Text="{Binding Price}"/>
                        </UniformGrid>
                    </DataTemplate>
                </ContentControl.ContentTemplate>
            </ContentControl>
        </Grid>
    </Grid>
</Window>
ViewModelBase.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Threading;

namespace WpfApp4.ViewModels
{
    public class ViewModelBase : INotifyPropertyChanged
    {

        public event PropertyChangedEventHandler PropertyChanged;

        protected void RaisePropertyChanged([CallerMemberName] string propertyName = "")
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
        
        protected bool SetProperty<T>(ref T t, T value, [CallerMemberName] string propertyName = "")
        {
            if (EqualityComparer<T>.Default.Equals(t, value))
            {
                return false;
            }
            else
            {
                t = value;
                RaisePropertyChanged(propertyName);
                return true;
            }
        }
    }
}
使用系统;
使用System.Collections.Generic;
使用系统组件模型;
使用System.Runtime.CompilerServices;
使用系统线程;
命名空间WpfApp4.ViewModels
{
公共类ViewModelBase:INotifyPropertyChanged
{
公共事件属性更改事件处理程序属性更改;
受保护的void RaisePropertyChanged([CallerMemberName]字符串propertyName=”“)
{
PropertyChanged?.Invoke(这是新的PropertyChangedEventArgs(propertyName));
}
受保护的bool SetProperty(参考T,T值,[CallerMemberName]字符串propertyName=”“)
{
if(EqualityComparer.Default.Equals(t,value))
{
返回false;
}
其他的
{
t=数值;
RaisePropertyChanged(propertyName);
返回true;
}
}
}
}

将其添加到
窗口。参考资料
。当然,必须为
MainForm
设置
DataContext

<Window>
    <Window.Resources>
        <DataTemplate DataType="{x:Type xmlnsForVewModel:MainViewModel}">
            <ProductPage/>
        </DataTemplate>
    </Window.Resources>
</Window>


如果对于
ProductPage
HomeViewModel
应该是
DataContext
,那么
HomeViewModel
必须具有
Cars
属性,而不是
MainViewModel

对不起,我忘了提到页面更改正在工作。我编辑了这本书。支票,请。ContentControl的CurrentPage绑定正在工作,但绑定在ProductPage.xaml中不起作用,尽管理论上它们具有相同的功能context@dotsqlcode是否还会显示
ProductPage
?你确定没有在
UserControl
的代码隐藏中设置
DataContext
?我编辑了queshion。DataContext已设置,但我忘了提及这一点。我正在编辑我的答案,您可以生成演示。您在输出窗口中是否有任何错误?@默认值否,我希望我的应用上有项目,但DataContext没有任何功能,因为我的视图已加载(ProductPage.xaml)。对不起,我是说在Visual Studio中显示状态消息。WPF在显示大量信息方面相当出色。您可以在“ERROR”之后在该窗口中搜索。hm。。我想我明白你的问题了。查看是否有助于您在窗口的数据上下文中设置
MainViewModel
。代码中不清楚UserControl在窗口布局中是如何使用的。请说明这一点,因为这对于了解问题的原因可能很重要。
using System.Collections.ObjectModel;

namespace WpfApp4.ViewModels
{
    class MainWindowViewModel : ViewModelBase
    {
        public ObservableCollection<CarViewModel> ItemsSource { get; } = new ObservableCollection<CarViewModel>();

        private CarViewModel selectedCarViewModel;

        public CarViewModel SelectedCarViewModel
        {
            get { return this.selectedCarViewModel; }
            set { SetProperty(ref this.selectedCarViewModel, value); }
        }

        public MainWindowViewModel()
        {
            ItemsSource.Add(new CarViewModel() { Name = "BMW", Volume = 10, Price = 100 });
            ItemsSource.Add(new CarViewModel() { Name = "Toyota", Volume = 5, Price = 80 });
            ItemsSource.Add(new CarViewModel() { Name = "Benz", Volume = 20, Price = 150 });

            // don't let view binding null value, so here initialze property "SelectedCarViewModel"
            this.selectedCarViewModel = ItemsSource[0];
        }
    }
}
namespace WpfApp4.ViewModels
{
    class CarViewModel : ViewModelBase
    {
        private string name;

        public string Name
        {
            get { return this.name; }
            set { SetProperty(ref this.name, value); }
        }

        private float volume;

        public float Volume
        {
            get { return this.volume; }
            set { SetProperty(ref this.volume, value); }
        }

        private decimal price;

        public decimal Price
        {
            get { return this.price; }
            set { SetProperty(ref this.price, value); }
        }
    }
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Threading;

namespace WpfApp4.ViewModels
{
    public class ViewModelBase : INotifyPropertyChanged
    {

        public event PropertyChangedEventHandler PropertyChanged;

        protected void RaisePropertyChanged([CallerMemberName] string propertyName = "")
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
        
        protected bool SetProperty<T>(ref T t, T value, [CallerMemberName] string propertyName = "")
        {
            if (EqualityComparer<T>.Default.Equals(t, value))
            {
                return false;
            }
            else
            {
                t = value;
                RaisePropertyChanged(propertyName);
                return true;
            }
        }
    }
}
<Window>
    <Window.Resources>
        <DataTemplate DataType="{x:Type xmlnsForVewModel:MainViewModel}">
            <ProductPage/>
        </DataTemplate>
    </Window.Resources>
</Window>