Я использую шаблон MVVM и натолкнулся на эту проблему.
Я хотел бы создать объект SpecificProductViewModel, передав продукт, для которого я хочу заданное представление c по параметру, из моего класса ProductListViewModel ( который содержит все продукты) со следующей функцией:
private void OnProductNav(tblMATProduct product)
{
if (product != null)
{
CurrentProduct = product;
SpecificProductVM = new SpecificProductViewModel(product);
CurrentProductViewModel = SpecificProductVM;
SpecificProductVM.Product = product;
}
}
Затем мне нужно было бы присвоить DataContext моего SpecificProductView для моей SpecificProductViewModel в коде кода следующим образом:
DataContext = new SpecificProductViewModel();
Проблема, однако, заключается в том, что при этом создается новый объект SpecificProductViewModel, и поэтому DataContext не использует данные (продукт tblMATProduct), передаваемые параметром при создании объекта из класса ProductListViewModel.
Будет есть способ назначить DataContext непосредственно из класса ProductListViewModel или получить продукт tblMATProduct из кода или в xaml?
Заранее спасибо!
Редактировать 1: Я думал, что ли ke Lennart, выполнив это:
DataContext = new ProductListViewModel();
Проблема, однако, заключается в том, что экземпляр specificViewModel должен быть создан сразу после того, как пользователь щелкнет по указанному c продукту.
Поэтому, если мы создадим новый экземпляр 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 со всеми моими продуктами, где пользователь может выбрать строку (указать c продукт) нажав на нее.
<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
, экземпляр View
будет создан автоматически при создании экземпляра ViewModel
через шаблон данных xaml в ProductListView.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: Объяснение того, как обрабатывается шаблон данных
Вот ContentControl, который запускает представление SpecificProductView. Он использует
<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); }
}