将视图从另一个 ViewModel 绑定到 DataContext Class
Binding View to DataContext from another ViewModel Class
我正在使用 MVVM 模式并遇到了这个问题。
我想通过从我的 ProductListViewModel class(包含所有产品)的参数传递我想要其特定视图的产品来创建一个 SpecificProductViewModel 对象,函数如下:
private void OnProductNav(tblMATProduct product)
{
if (product != null)
{
CurrentProduct = product;
SpecificProductVM = new SpecificProductViewModel(product);
CurrentProductViewModel = SpecificProductVM;
SpecificProductVM.Product = product;
}
}
然后我需要在代码隐藏中将我的 SpecificProductView 的 DataContext 分配给我的 SpecificProductViewModel,如下所示:
DataContext = new SpecificProductViewModel();
然而,问题是通过这样做创建了一个新的 SpecificProductViewModel 对象,因此 DataContext 没有使用从 ProductListViewModel 创建对象时通过参数传递的数据(tblMATProduct 产品)class .
是否可以直接从 ProductListViewModel 分配 DataContext class 或者能够从代码隐藏或 xaml 中获取 tblMATProduct 产品?
提前致谢!
编辑 1: 我像伦纳特那样思考:
DataContext = new ProductListViewModel();
但问题是需要在用户单击特定产品后立即创建特定的 ViewModel 实例。
因此,如果我们在代码隐藏中创建一个新的 ProductListViewModel 实例并为其分配 ProductListViewModel,该实例将不知道用户单击了什么,也不会调用函数 OnProductNav。
编辑 2: 增加精度。
class ProductListViewModel : ViewModelBase
{
private SpecificProductViewModel SpecificProductVM;
public tblMATProduct CurrentProduct { set; get; }
public ViewModelBase CurrentProductViewModel
{
get { return _currentProductViewModel; }
set { SetProperty(ref _currentProductViewModel, value); }
}
public ProductListViewModel() {
ProductNavCommand = new MyICommand<tblMATProduct>(OnProductNav);
}
private void OnProductNav(tblMATProduct product)
{
if (product != null)
{
SpecificProductVM = new SpecificProductViewModel(product);
CurrentProductViewModel = SpecificProductVM;
}
}
}
在我的 ProductListView 中,我有一个包含我所有产品的 DataGrid,用户可以在其中 select 通过单击一行(特定产品)。
<Datagrid>
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<i:InvokeCommandAction Command="{Binding ProductNavCommand}"
CommandParameter="{Binding Path=SelectedItem, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGrid}}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</DataGrid>
这是我的 SpecificProductViewModel
class SpecificProductViewModel : ViewModelBase
{
private tblMATProduct _product;
public tblMATProduct Product
{
get { return _product; }
set { SetProperty(ref _product, value); }
}
public SpecificProductViewModel()
{
}
public SpecificProductViewModel(tblMATProduct product)
{
Product = product;
}
}
下面是来自 SpecificProductView.xaml 的几行代码,它们将绑定到 SpecificProductViewModel.cs
<Grid Background="Red" Height="800" Width="1350" HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock Text="{Binding Product.FormatID}" FontSize="32" Foreground="White" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<TextBlock Text="{Binding Product.SpecificProductVM, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}" FontSize="32" Foreground="White" HorizontalAlignment="Center" VerticalAlignment="Bottom"/>
<TextBlock Text="{Binding Product.GradeID}" FontSize="32" Foreground="White" HorizontalAlignment="Center" VerticalAlignment="Top"/>
</Grid>
编辑 3:添加另一层精度
回答mm8的问题,因为我刚开始使用WPF和MVVM,我一直假设如果View's DataContext
绑定到对应的ViewModel
,[=的实例24=] 将在通过 ProductListView.xaml
中的 xaml 数据模板创建 ViewModel
实例时自动创建:
<DataTemplate DataType = "{x:Type viewModels:SpecificProductViewModel}">
<products:SpecificProductView/>
</DataTemplate>
这是我通常创建 DataContext
的地方。
SpecificProductView.xaml.cs
public partial class SpecificProductView : UserControl
{
public SpecificProductView()
{
InitializeComponent();
DataContext = new SpecificProductViewModel();
}
}
编辑 4:解释如何处理数据模板
这是启动 SpecificProductView 视图的 ContentControl。它使用
<Grid HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Column="0" Grid.Row="0">
<ContentControl Content="{Binding CurrentProductViewModel}"/>
</Grid>
它绑定到确定应在 SpecificProductView
中显示的产品。
public ViewModelBase CurrentProductViewModel
{
get { return _currentProductViewModel; }
set { SetProperty(ref _currentProductViewModel, value); }
}
由于您使用的 ContentControl
绑定到您在视图模型中设置的 CurrentProductViewModel
属性,因此您应该简单地删除以下设置 DataContext
的 UserControl
到 XAML:
的视图模型的新实例
<UserControl.DataContext>
<viewModel:SpecificProductViewModel/>
</UserControl.DataContext>
然后 UserControl
将继承 CurrentProductViewModel
返回的视图模型作为它的 DataContext
。
通常来说,在 XAML 和代码隐藏中显式设置 UserControl
的 DataContext
属性 是个坏主意,因为这打破了 DataContext
从父元素的继承。
我正在使用 MVVM 模式并遇到了这个问题。
我想通过从我的 ProductListViewModel class(包含所有产品)的参数传递我想要其特定视图的产品来创建一个 SpecificProductViewModel 对象,函数如下:
private void OnProductNav(tblMATProduct product)
{
if (product != null)
{
CurrentProduct = product;
SpecificProductVM = new SpecificProductViewModel(product);
CurrentProductViewModel = SpecificProductVM;
SpecificProductVM.Product = product;
}
}
然后我需要在代码隐藏中将我的 SpecificProductView 的 DataContext 分配给我的 SpecificProductViewModel,如下所示:
DataContext = new SpecificProductViewModel();
然而,问题是通过这样做创建了一个新的 SpecificProductViewModel 对象,因此 DataContext 没有使用从 ProductListViewModel 创建对象时通过参数传递的数据(tblMATProduct 产品)class .
是否可以直接从 ProductListViewModel 分配 DataContext class 或者能够从代码隐藏或 xaml 中获取 tblMATProduct 产品?
提前致谢!
编辑 1: 我像伦纳特那样思考:
DataContext = new ProductListViewModel();
但问题是需要在用户单击特定产品后立即创建特定的 ViewModel 实例。
因此,如果我们在代码隐藏中创建一个新的 ProductListViewModel 实例并为其分配 ProductListViewModel,该实例将不知道用户单击了什么,也不会调用函数 OnProductNav。
编辑 2: 增加精度。
class ProductListViewModel : ViewModelBase
{
private SpecificProductViewModel SpecificProductVM;
public tblMATProduct CurrentProduct { set; get; }
public ViewModelBase CurrentProductViewModel
{
get { return _currentProductViewModel; }
set { SetProperty(ref _currentProductViewModel, value); }
}
public ProductListViewModel() {
ProductNavCommand = new MyICommand<tblMATProduct>(OnProductNav);
}
private void OnProductNav(tblMATProduct product)
{
if (product != null)
{
SpecificProductVM = new SpecificProductViewModel(product);
CurrentProductViewModel = SpecificProductVM;
}
}
}
在我的 ProductListView 中,我有一个包含我所有产品的 DataGrid,用户可以在其中 select 通过单击一行(特定产品)。
<Datagrid>
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<i:InvokeCommandAction Command="{Binding ProductNavCommand}"
CommandParameter="{Binding Path=SelectedItem, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGrid}}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</DataGrid>
这是我的 SpecificProductViewModel
class SpecificProductViewModel : ViewModelBase
{
private tblMATProduct _product;
public tblMATProduct Product
{
get { return _product; }
set { SetProperty(ref _product, value); }
}
public SpecificProductViewModel()
{
}
public SpecificProductViewModel(tblMATProduct product)
{
Product = product;
}
}
下面是来自 SpecificProductView.xaml 的几行代码,它们将绑定到 SpecificProductViewModel.cs
<Grid Background="Red" Height="800" Width="1350" HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock Text="{Binding Product.FormatID}" FontSize="32" Foreground="White" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<TextBlock Text="{Binding Product.SpecificProductVM, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}" FontSize="32" Foreground="White" HorizontalAlignment="Center" VerticalAlignment="Bottom"/>
<TextBlock Text="{Binding Product.GradeID}" FontSize="32" Foreground="White" HorizontalAlignment="Center" VerticalAlignment="Top"/>
</Grid>
编辑 3:添加另一层精度
回答mm8的问题,因为我刚开始使用WPF和MVVM,我一直假设如果View's DataContext
绑定到对应的ViewModel
,[=的实例24=] 将在通过 ProductListView.xaml
中的 xaml 数据模板创建 ViewModel
实例时自动创建:
<DataTemplate DataType = "{x:Type viewModels:SpecificProductViewModel}">
<products:SpecificProductView/>
</DataTemplate>
这是我通常创建 DataContext
的地方。
SpecificProductView.xaml.cs
public partial class SpecificProductView : UserControl
{
public SpecificProductView()
{
InitializeComponent();
DataContext = new SpecificProductViewModel();
}
}
编辑 4:解释如何处理数据模板
这是启动 SpecificProductView 视图的 ContentControl。它使用
<Grid HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Column="0" Grid.Row="0">
<ContentControl Content="{Binding CurrentProductViewModel}"/>
</Grid>
它绑定到确定应在 SpecificProductView
中显示的产品。
public ViewModelBase CurrentProductViewModel
{
get { return _currentProductViewModel; }
set { SetProperty(ref _currentProductViewModel, value); }
}
由于您使用的 ContentControl
绑定到您在视图模型中设置的 CurrentProductViewModel
属性,因此您应该简单地删除以下设置 DataContext
的 UserControl
到 XAML:
<UserControl.DataContext>
<viewModel:SpecificProductViewModel/>
</UserControl.DataContext>
然后 UserControl
将继承 CurrentProductViewModel
返回的视图模型作为它的 DataContext
。
通常来说,在 XAML 和代码隐藏中显式设置 UserControl
的 DataContext
属性 是个坏主意,因为这打破了 DataContext
从父元素的继承。