C# 将数据绑定到WPF(MVVM)中的子视图
我正在尝试使用WPF和MVVM协议构建一个应用程序。应用程序有一个窗口和多个视图(UserControls)。其中一个视图中还包含子视图,用于显示不同的数据 我的问题 我无法理解如何将数据绑定到子视图。我试图理解数据是如何绑定的,但我只能将数据绑定到一个级别 代码 下面是一些代码。我希望这能使我更容易理解我的问题 App.xaml.csC# 将数据绑定到WPF(MVVM)中的子视图,c#,.net,wpf,mvvm,data-binding,C#,.net,Wpf,Mvvm,Data Binding,我正在尝试使用WPF和MVVM协议构建一个应用程序。应用程序有一个窗口和多个视图(UserControls)。其中一个视图中还包含子视图,用于显示不同的数据 我的问题 我无法理解如何将数据绑定到子视图。我试图理解数据是如何绑定的,但我只能将数据绑定到一个级别 代码 下面是一些代码。我希望这能使我更容易理解我的问题 App.xaml.cs public partial class App : Application { private Engine _engine; prote
public partial class App : Application
{
private Engine _engine;
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
MainWindow window = new MainWindow();
_engine = new Engine("test");
var viewModel = new MainWindowViewModel(_engine);
EventHandler handler = null;
handler = delegate
{
viewModel.RequestClose -= handler;
window.Close();
};
viewModel.RequestClose += handler;
window.DataContext = viewModel;
window.Show();
}
}
public WorkspaceViewModel()
{
_currentView = new InjectorView();
}
public UserControl CurrentView
{
get { return _currentView; }
}
public WorkspaceView()
{
InitializeComponent();
this.DataContext = new WorkspaceViewModel();
}
这里是我创建引擎对象并将其传递给MainWindowViewModel的地方,我想进一步绑定视图层次结构
main window.xaml
<Window
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:"
xmlns:ViewModels="clr-namespace:ViewModels"
xmlns:View="clr-namespace:Views"
x:Class="MainWindow"
Title="title" Height="800" Width="1200"
WindowStartupLocation="CenterScreen" Icon="Resources/Images/logo.png"
>
<DockPanel Margin="0" Background="#FF4F4F4F" LastChildFill="True">
<Menu DockPanel.Dock="Top" Height="20">
<MenuItem Header="File">
<MenuItem Header="Exit"/>
</MenuItem>
</Menu>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" MinWidth="200" MaxWidth="200"/>
<ColumnDefinition Width="5*"/>
</Grid.ColumnDefinitions>
<View:TabView Grid.Column="0"/>
<View:WorkspaceView Grid.Column="1"/>
</Grid>
</DockPanel>
<UserControl x:Class="Views.WorkspaceView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Views"
xmlns:ViewModels="clr-namespace:ViewModels"
mc:Ignorable="d"
d:DesignHeight="750"
d:DesignWidth="1000"
d:DataContext="{d:DesignInstance ViewModels:WorkspaceViewModel}"
>
<Grid>
<Label x:Name="label" Height="750" VerticalAlignment="Top" FontSize="60" Foreground="White" Content="{Binding Engine.BarCode}"/>
<Grid Margin="40">
<Grid.Background>
<ImageBrush ImageSource="/;component/Resources/Images/logo.png" Stretch="Uniform"/>
</Grid.Background>
<ContentPresenter Content="{Binding CurrentView}"/>
</Grid>
<DockPanel>
<!--ContentPresenter Content="{Binding CurrentView}"/-->
</DockPanel>
</Grid>
<UserControl x:Class="Views.InjectorView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Views"
xmlns:ViewModels="clr-namespace:ViewModels"
mc:Ignorable="d"
d:DesignHeight="750"
d:DesignWidth="1000"
d:DataContext="{d:DesignInstance ViewModels:InjectorViewModel}"
>
<Grid Background="#FFAEAEAE">
<Label x:Name="label1" Content="{Binding Engine.BarCode}"/>
</Grid>
</UserControl>
- 更新:
\u currentView=new InjectorView()代码>仅用于测试,当前视图应根据在另一个视图中按下的按钮进行更改*
public partial class App : Application
{
private Engine _engine;
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
MainWindow window = new MainWindow();
_engine = new Engine("test");
var viewModel = new MainWindowViewModel(_engine);
EventHandler handler = null;
handler = delegate
{
viewModel.RequestClose -= handler;
window.Close();
};
viewModel.RequestClose += handler;
window.DataContext = viewModel;
window.Show();
}
}
public WorkspaceViewModel()
{
_currentView = new InjectorView();
}
public UserControl CurrentView
{
get { return _currentView; }
}
public WorkspaceView()
{
InitializeComponent();
this.DataContext = new WorkspaceViewModel();
}
InjectorView.xaml
<Window
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:"
xmlns:ViewModels="clr-namespace:ViewModels"
xmlns:View="clr-namespace:Views"
x:Class="MainWindow"
Title="title" Height="800" Width="1200"
WindowStartupLocation="CenterScreen" Icon="Resources/Images/logo.png"
>
<DockPanel Margin="0" Background="#FF4F4F4F" LastChildFill="True">
<Menu DockPanel.Dock="Top" Height="20">
<MenuItem Header="File">
<MenuItem Header="Exit"/>
</MenuItem>
</Menu>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" MinWidth="200" MaxWidth="200"/>
<ColumnDefinition Width="5*"/>
</Grid.ColumnDefinitions>
<View:TabView Grid.Column="0"/>
<View:WorkspaceView Grid.Column="1"/>
</Grid>
</DockPanel>
<UserControl x:Class="Views.WorkspaceView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Views"
xmlns:ViewModels="clr-namespace:ViewModels"
mc:Ignorable="d"
d:DesignHeight="750"
d:DesignWidth="1000"
d:DataContext="{d:DesignInstance ViewModels:WorkspaceViewModel}"
>
<Grid>
<Label x:Name="label" Height="750" VerticalAlignment="Top" FontSize="60" Foreground="White" Content="{Binding Engine.BarCode}"/>
<Grid Margin="40">
<Grid.Background>
<ImageBrush ImageSource="/;component/Resources/Images/logo.png" Stretch="Uniform"/>
</Grid.Background>
<ContentPresenter Content="{Binding CurrentView}"/>
</Grid>
<DockPanel>
<!--ContentPresenter Content="{Binding CurrentView}"/-->
</DockPanel>
</Grid>
<UserControl x:Class="Views.InjectorView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Views"
xmlns:ViewModels="clr-namespace:ViewModels"
mc:Ignorable="d"
d:DesignHeight="750"
d:DesignWidth="1000"
d:DataContext="{d:DesignInstance ViewModels:InjectorViewModel}"
>
<Grid Background="#FFAEAEAE">
<Label x:Name="label1" Content="{Binding Engine.BarCode}"/>
</Grid>
</UserControl>
但是如果我从WorkspaceView.xaml中删除d:DataContext=“{d:DesignInstance ViewModels:WorkspaceViewModel}”
,并添加this.DataContext=new WorkspaceViewModel()
到c#文件中,对于xaml代码,它将显示当前视图(InjectorView)。现在唯一的问题是,当我尝试在InjectorView{Binding Engine.BarCode}
中绑定一些数据时,它不会显示与以前相同的字符串(我想它不再是对象的同一个实例了??)
我错过了什么?我是否完全错误地解释了MVVM和wpf
(由于产品的原因,我不得不删除一些代码(例如名称空间)您肯定误解了很多 首先,
\u currentView=newinjectorview()代码>不应出现在ViewModel中。ViewModels不应该包含任何可视类(您自己的视图类和UI类)的任何引用。您应该为该视图实例化ViewModel
接下来,如果该CurrentView
始终是InjectorView
的一个实例(这意味着它不可能是其他的),那么您可以简单地执行以下操作:
<View:InjectorView>
<View:InjectorView.DataContext>
<ViewModel:InjectorViewModel />
<View:InjectorView.DataContext>
</View:InjectorView>
工作空间视图:
<ContentControl Content="{Binding MyCurrentView}">
<ContentControl.Resources>
<DataTemplate DataType="{x:Type ViewModels:InjectorViewModel}">
<local:InjectorView />
</DataTemplate>
<DataTemplate DataType="{x:Type ViewModels:MySecondViewModel}">
<local:MySecondView />
</DataTemplate>
.....
....
</ContentControl.Resources>
</ContentControl>
您无法从视图实例化ViewModel,因为对于单例实现,必须将构造函数设置为私有的。您将改为提供对静态实例的绑定
总的来说,我只需要使用一个单例类来充当存储库。这对我来说似乎很容易实现。谢谢。这澄清了“d:DataContext=“{d:DesignInstance ViewModels:InjectorViewModel}”为什么我删除这一行时它没有更改任何内容:)关于将视图与viewmodel分离(对于currentView)我可以理解。我忘了说视图将更改为另一个视图,而不总是InjectorView。我该如何处理这个问题?非常感谢@Jai为您提供的时间。我将尝试实施这个策略,并看看它是如何进行的。谢谢,实施您的建议效果很好。我正在努力解决如何从顶部视图绑定数据的问题(主窗口)转到InjectorView。你有什么指导方针如何处理这个问题吗?@robin再次更新。