wpf - 从另一个 ViewModel 类将 View 绑定(bind)到 DataContext

标签 wpf mvvm view viewmodel datacontext

我正在使用 MVVM 模式并遇到了这个问题。

我想通过使用以下函数从我的 ProductListViewModel 类(包含所有产品)传递我想要特定 View 的产品来创建一个 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 的新对象,因此当从 ProductListViewModel 类创建对象时,DataContext 不使用参数传递的数据(tblMATProduct 产品)。

有没有办法直接从 ProductListViewModel 类分配 DataContext 或者能够从代码隐藏或 xaml 中获取 tblMATProduct 产品?

提前致谢!

编辑 1:通过这样做,我像 Lennart 一样思考:
DataContext = new ProductListViewModel(); 

但问题是,需要在用户单击特定产品后立即创建 specificViewModel 实例。

因此,如果我们在代码隐藏中创建一个 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,用户可以通过单击它来选择一行(特定产品)。
<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 的几行代码,它们将绑定(bind)到 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绑定(bind)到对应的ViewModelView 的实例将在 ViewModel 时自动创建实例是通过 ProductListView.xaml 中的 xaml 数据模板创建的:
<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 View 的ContentControl。它用
    <Grid HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Column="0" Grid.Row="0">
        <ContentControl Content="{Binding CurrentProductViewModel}"/>
    </Grid>

它绑定(bind)到决定哪个产品应该显示在 SpecificProductView 中的 this。 .
public ViewModelBase CurrentProductViewModel
{
    get { return _currentProductViewModel; }
    set { SetProperty(ref _currentProductViewModel, value); }
}

最佳答案

由于您使用的是 ContentControl绑定(bind)到 CurrentProductViewModel您在 View 模型中设置的属性,您应该简单地删除以下设置 DataContext 的部分的UserControl从 XAML 到 View 模型的新实例:

<UserControl.DataContext>
    <viewModel:SpecificProductViewModel/>
</UserControl.DataContext>
UserControl然后将继承 CurrentProductViewModel 返回的 View 模型作为它的DataContext .

一般来说,显式设置 DataContext 是一个坏主意。 UserControl 的属性(property),无论是在 XAML 中还是在代码隐藏中,因为这会破坏 DataContext 的继承。从父元素。

关于wpf - 从另一个 ViewModel 类将 View 绑定(bind)到 DataContext,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61331099/

相关文章:

wpf - 使用 Log4Net 记录 WPF 数据绑定(bind)错误

c# - 如何单独设置 StackPanels 边距?

c# - 用泛型抽象一个类

android - 如何使用Databinding android更新editview中的ontextchanged的textview

iphone - xcode 中只有一个 View 自动旋转?

c# - 如何通过 Binding 在 Canvas 中显示项目

c# - 如何在与主窗口相同的监视器上打开对话框( View )

ios - 如何以编程方式创建默认 slider 值?

c# - MVVM 数据绑定(bind)

oracle - ORA-01031:选择 View 时特权不足