Я занимаюсь разработкой приложения WPF с использованием архитектуры MVVM, но у меня возникла проблема с установкой текущей модели в ViewModel.
Что ж, в настоящее время я пытаюсь установить модель, поступающую из ViewModel (A: SectionCustomersViewModel) к другому (B: CustomerViewModel), но каждый раз, когда устанавливается «currentModel» (свойство CustomerViewModel), он просто равен нулю, и очевидно, что связанный элемент View для CustomerViewModel ничего не показывает в элементах управления.
Я уже пытался настроить модель непосредственно на ViewModel, но это не сработало, поэтому я изменил стратегию, используя своего рода шаблон издатель-подписчик, но он тоже не сработал.
Следует отметить, что я выполнил тест с некоторым фиктивным элементом данных, чтобы увидеть, установлены ли пользовательские элементы управления (текстовое поле, поле со списком и т. Д.) И эффективно ли они установлены.
Время увидеть код для большей ясности (для более ясного и короткого кода я просто удаляю ненужные строки).
ViewModel A (SectionCustomersViewModel).
class SectionCustomersViewModel : ObservableObject, IPageViewModel
{
private event Action<CustomerModel> CustomerToCustomerViewModel;
public string Name => "Customers".ToUpper();
public string Icon => "images/UserGroups_96px.png";
private IPageViewModel _currentPageViewModel;
private ICommand _changePageCommand;
private ICommand _addCustomerCommand;
private ICommand _editCustomerCommand;
public SectionCustomersViewModel()
{
// Add available pages
CustomersViewModel = new CustomersViewModel();
CustomerViewModel = new CustomerViewModel();
CustomerToCustomerViewModel += (CustomerViewModel as CustomerViewModel).ReceiveCustomer;
// Set starting page
CurrentPageViewModel = CustomersViewModel;
}
#region Properties
#region Pages
public IPageViewModel CustomersViewModel { get; }
public IPageViewModel CustomerViewModel { get; }
#endregion
public IPageViewModel CurrentPageViewModel
{
get => _currentPageViewModel;
set
{
if (_currentPageViewModel != value)
{
_currentPageViewModel = value;
OnPropertyChanged("CurrentPageViewModel");
}
}
}
#endregion
#region Commands
public ICommand BackPageCommand
{
get
{
if (_changePageCommand == null)
_changePageCommand = new CommandHandler(p => ChangeViewModel(p as IPageViewModel), p => p is IPageViewModel);
return _changePageCommand;
}
}
public ICommand AddCustomerCommand
{
get
{
if (_addCustomerCommand == null)
_addCustomerCommand = new CommandHandler(param => AddCustomer());
return _addCustomerCommand;
}
}
public ICommand EditCustomerCommand
{
get
{
if (_editCustomerCommand == null)
_editCustomerCommand = new CommandHandler(c => EditCustomer(c as CustomerModel));
return _editCustomerCommand;
}
}
#endregion
#region Methods
private void ChangeViewModel(IPageViewModel viewModel)
=> CurrentPageViewModel = viewModel;
private void EditCustomer(CustomerModel customer)
{
CurrentPageViewModel = CustomerViewModel;
CustomerToCustomerViewModel?.Invoke(customer);
}
private void AddCustomer()
{
CurrentPageViewModel = CustomerViewModel;
CustomerToCustomerViewModel?.Invoke(new CustomerModel());
}
#endregion
}
Представление для ViewModel A
<UserControl x:Class="Presentation.View.Customer.SectionCustomersView"
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:vm="clr-namespace:Presentation.ViewModel.Customer"
xmlns:v="clr-namespace:Presentation.View.Customer"
mc:Ignorable="d" d:DesignWidth="800" Height="Auto">
<UserControl.Resources>
<vm:SectionCustomersViewModel x:Key="SectionCustomersVM"/>
<DataTemplate DataType="{x:Type vm:CustomersViewModel}">
<v:CustomersView />
</DataTemplate>
<DataTemplate DataType="{x:Type vm:CustomerViewModel}">
<v:CustomerView />
</DataTemplate>
</UserControl.Resources>
<UserControl.DataContext>
<Binding Source="{StaticResource SectionCustomersVM}"/>
</UserControl.DataContext>
<Grid>
<ContentControl Content="{Binding CurrentPageViewModel}" />
</Grid>
ViewModel B (CustomerViewModel).
class CustomerViewModel : ObservableObject, IPageViewModel
{
#region Attributes
private CustomerModel _currentCustomer;
private AddressModel _currentAddress;
private ICommand _loadedCustomerCommand;
private ICommand _saveCustomerCommand;
#endregion
#region IPageViewModel's properties
public string Name => "Customer";
public string Icon => string.Empty;
#endregion
#region Properties
public Action<CustomerModel> ReceiveCustomer
=> SetCustomer;
public List<CountryModel> Countries => CountryModel.Load();
public List<ZoneModel> Zones => ZoneModel.Load();
public List<CustomerGroupModel> CustomerGroups => CustomerGroupModel.Load();
public CustomerModel CurrentCustomer
{
get => _currentCustomer;
set
{
if (value != _currentCustomer)
{
_currentCustomer = value;
OnPropertyChanged("CurrentCustomer");
}
}
}
public AddressModel CurrentAddress
{
get => _currentAddress;
set
{
if (value != _currentAddress)
{
_currentAddress = value;
OnPropertyChanged("CurrentAddress");
}
}
}
#endregion
#region Commands
public ICommand LoadedCommand
{
get
{
if (_loadedCustomerCommand == null)
_loadedCustomerCommand = new CommandHandler(o => LoadExtraData());
return _loadedCustomerCommand;
}
}
public ICommand SaveCommand
{
get
{
if (_saveCustomerCommand == null)
{
_saveCustomerCommand = new CommandHandler(
param => SaveCustomer(),
param => (CurrentCustomer != null)
);
}
return _saveCustomerCommand;
}
}
#endregion
#region Methods
private void SetCustomer(CustomerModel customer)
=> CurrentCustomer = customer;
private void LoadExtraData()
{
//if (CurrentCustomer.Address_id == 0)
// return;
//// Dummy data, just to test if the binding with the view is correctly setted.
//CurrentAddress = new AddressModel()
//{
// Firstname = "John",
// Lastname = "Doe",
// Address_1 = "Nowhere",
// City = "Somewhere",
// Company = "A-Z",
// Country_id = 1
//};
//// If the currentCustomer is setted here, it works fine.
//CurrentCustomer = new CustomerModel()
//{
// Firstname = "Some",
// Lastname = "One",
// Email = "somemail@mail.com",
// Telephone = "555-000-000",
// Status = true,
// Safe = false,
// Newsletter = false,
// Customer_group_id = 1
//};
}
private void SaveCustomer()
{
// You would implement your Product save here
CurrentAddress.Save();
CurrentCustomer.Save();
}
#endregion
}
Просмотр для ViewModel B
<UserControl x:Class="Presentation.View.Customer.CustomerView"
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:vm="clr-namespace:Presentation.ViewModel.Customer"
xmlns:v="clr-namespace:Presentation.View.Customer"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
VerticalAlignment="Stretch"
VerticalContentAlignment="Stretch">
<UserControl.Resources>
<vm:CustomerViewModel x:Key="CustomerViewModel" />
</UserControl.Resources>
<UserControl.DataContext>
<Binding Source="{StaticResource CustomerViewModel}" />
</UserControl.DataContext>
<!-- Bind UserControl Loaded event to CustomersVM's LoadedCommand -->
<i:Interaction.Triggers>
<i:EventTrigger EventName="Loaded">
<i:InvokeCommandAction Command="{Binding LoadedCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="160*" />
<RowDefinition Height="25*"/>
</Grid.RowDefinitions>
<Button Grid.Row="0" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Width="32" Height="32"
Command="{Binding DataContext.BackPageCommand, RelativeSource={RelativeSource AncestorType={x:Type v:SectionCustomersView}}}"
CommandParameter="{Binding DataContext.CustomersViewModel, RelativeSource={RelativeSource AncestorType={x:Type v:SectionCustomersView}}}">
<Image Source="/Presentation;Component/images/BackArrow_32px.png" Stretch="Uniform"/>
</Button>
<Label Grid.Row="0" Content="{Binding Name}" HorizontalAlignment="Left" VerticalAlignment="Top"
HorizontalContentAlignment="Right" VerticalContentAlignment="Center" Width="Auto" FontSize="24" FontFamily="Century Gothic" FontStretch="Expanded" BorderBrush="#FF4C4D5A" Height="37" Margin="67,10,0,0"/>
<Label Grid.Row="0" Content="{Binding Icon}" HorizontalAlignment="Left" VerticalAlignment="Top"
HorizontalContentAlignment="Left" VerticalContentAlignment="Bottom" Width="Auto" FontSize="16" FontFamily="Century Gothic" FontStretch="Expanded" Height="37" Margin="154,10,0,0" Foreground="#FF464646"/>
<Separator Grid.Row="0" Height="20" Margin="10,52,10,0" VerticalAlignment="Top"/>
<ScrollViewer Grid.Row="1" VerticalScrollBarVisibility="Auto"
HorizontalContentAlignment="Center" VerticalContentAlignment="Top">
<WrapPanel>
<GroupBox Header="Detalles" FontFamily="Century gothic" Height="Auto" Width="367"
VerticalContentAlignment="Top" VerticalAlignment="Top">
<Grid Margin="0">
<StackPanel Orientation="Horizontal" Height="Auto"
VerticalAlignment="Top" Width="Auto" Margin="35,10,0,0">
<Label Grid.Row="1" Content="Firstname"
HorizontalAlignment="Left" VerticalAlignment="Center"
HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Center" Width="auto" FontSize="16" FontFamily="Century Gothic" FontStretch="Expanded" Height="37" Foreground="#FF464646"/>
<TextBox HorizontalAlignment="Right" VerticalAlignment="Center"
VerticalContentAlignment="Center" HorizontalContentAlignment="Left"
Height="23" TextWrapping="NoWrap" Width="135"
Text="{Binding CurrentCustomer.Firstname}"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Height="Auto"
VerticalAlignment="Top" Margin="35,52,0,0">
<Label Grid.Row="1" Content="Lastname"
HorizontalAlignment="Left" VerticalAlignment="Center"
HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Center" Width="auto" FontSize="16" FontFamily="Century Gothic" FontStretch="Expanded" Height="37" Foreground="#FF464646"/>
<TextBox HorizontalAlignment="Right" VerticalAlignment="Center"
VerticalContentAlignment="Center" HorizontalContentAlignment="Left"
Height="23" TextWrapping="NoWrap" Width="135"
Text="{Binding CurrentCustomer.Lastname}"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Height="Auto"
VerticalAlignment="Top" Margin="35,94,0,0">
<Label Grid.Row="1" Content="Email"
HorizontalAlignment="Left" VerticalAlignment="Center"
HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Center" Width="auto" FontSize="16" FontFamily="Century Gothic" FontStretch="Expanded" Height="37" Foreground="#FF464646"/>
<TextBox HorizontalAlignment="Right" VerticalAlignment="Center"
VerticalContentAlignment="Center" HorizontalContentAlignment="Left"
Height="23" TextWrapping="NoWrap" Width="135"
Text="{Binding CurrentCustomer.Email}"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Height="Auto"
VerticalAlignment="Top" Margin="35,136,0,0">
<Label Grid.Row="1" Content="Telephone"
HorizontalAlignment="Left" VerticalAlignment="Center"
HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Center" Width="auto" FontSize="16" FontFamily="Century Gothic" FontStretch="Expanded" Height="37" Foreground="#FF464646"/>
<TextBox HorizontalAlignment="Right" VerticalAlignment="Center"
VerticalContentAlignment="Center" HorizontalContentAlignment="Left"
Height="23" TextWrapping="NoWrap" Width="135"
Text="{Binding CurrentCustomer.Telephone}"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Height="Auto"
VerticalAlignment="Top" Margin="35,178,0,0">
<Label Grid.Row="1" Content="Customer Group"
HorizontalAlignment="Left" VerticalAlignment="Center"
HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Center" Width="auto" FontSize="16" FontFamily="Century Gothic" FontStretch="Expanded" Height="37" Foreground="#FF464646"/>
<ComboBox HorizontalAlignment="Right" VerticalAlignment="Center"
VerticalContentAlignment="Center" HorizontalContentAlignment="Left"
Height="23" Width="135"
ItemsSource="{Binding CustomerGroups}"
SelectedValuePath="Customer_Group_ID" DisplayMemberPath="Name"
SelectedValue="{Binding CurrentCustomer.Customer_group_id}"/>
</StackPanel>
</Grid>
</GroupBox>
<GroupBox Header="Domicilio" FontFamily="Century gothic" Height="377" Width="376"
VerticalAlignment="Top" VerticalContentAlignment="Top">
<Grid Margin="0">
<StackPanel Orientation="Horizontal" Height="Auto"
VerticalAlignment="Top" Width="Auto" Margin="35,10,0,0">
<Label Grid.Row="1" Content="Name"
HorizontalAlignment="Left" VerticalAlignment="Center"
HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Center" Width="auto" FontSize="16" FontFamily="Century Gothic" FontStretch="Expanded" Height="37" Foreground="#FF464646"/>
<TextBox HorizontalAlignment="Right" VerticalAlignment="Center"
VerticalContentAlignment="Center" HorizontalContentAlignment="Left"
Height="23" TextWrapping="NoWrap" Width="135"
Text="{Binding CurrentAddress.Firstname}"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Height="Auto"
VerticalAlignment="Top" Margin="35,52,0,0">
<Label Grid.Row="1" Content="Lastname"
HorizontalAlignment="Left" VerticalAlignment="Center"
HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Center" Width="auto" FontSize="16" FontFamily="Century Gothic" FontStretch="Expanded" Height="37" Foreground="#FF464646"/>
<TextBox HorizontalAlignment="Right" VerticalAlignment="Center"
VerticalContentAlignment="Center" HorizontalContentAlignment="Left"
Height="23" TextWrapping="NoWrap" Width="135"
Text="{Binding CurrentAddress.Lastname}"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Height="Auto"
VerticalAlignment="Top" Margin="35,94,0,0">
<Label Grid.Row="1" Content="Company"
HorizontalAlignment="Left" VerticalAlignment="Center"
HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Center" Width="auto" FontSize="16" FontFamily="Century Gothic" FontStretch="Expanded" Height="37" Foreground="#FF464646"/>
<TextBox HorizontalAlignment="Right" VerticalAlignment="Center"
VerticalContentAlignment="Center" HorizontalContentAlignment="Left"
Height="23" TextWrapping="NoWrap" Width="135"
Text="{Binding CurrentAddress.Company}"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Height="Auto"
VerticalAlignment="Top" Margin="35,136,0,0">
<Label Grid.Row="1" Content="Address"
HorizontalAlignment="Left" VerticalAlignment="Center"
HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Center" Width="auto" FontSize="16" FontFamily="Century Gothic" FontStretch="Expanded" Height="37" Foreground="#FF464646"/>
<TextBox HorizontalAlignment="Right" VerticalAlignment="Center"
VerticalContentAlignment="Center" HorizontalContentAlignment="Left"
Height="23" TextWrapping="NoWrap" Width="135"
Text="{Binding CurrentAddress.Address_1}"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Height="Auto"
VerticalAlignment="Top" Margin="35,178,10,0">
<Label Content="Ciudad"
HorizontalAlignment="Left" VerticalAlignment="Center"
HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Center" Width="auto" FontSize="16" FontFamily="Century Gothic" FontStretch="Expanded" Height="37" Foreground="#FF464646"/>
<TextBox HorizontalAlignment="Right" VerticalAlignment="Center"
VerticalContentAlignment="Center" HorizontalContentAlignment="Left"
Height="23" TextWrapping="NoWrap" Width="135"
Text="{Binding CurrentAddress.City}"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Height="Auto"
VerticalAlignment="Top" Margin="35,220,10,0">
<Label Grid.Row="1" Content="Postcode"
HorizontalAlignment="Left" VerticalAlignment="Center"
HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Center" Width="auto" FontSize="16" FontFamily="Century Gothic" FontStretch="Expanded" Height="37" Foreground="#FF464646"/>
<TextBox HorizontalAlignment="Right" VerticalAlignment="Center"
VerticalContentAlignment="Center" HorizontalContentAlignment="Left"
Height="23" TextWrapping="NoWrap" Width="135"
Text="{Binding CurrentAddress.Postcode}"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Height="Auto"
VerticalAlignment="Top" Margin="35,262,0,0">
<Label Grid.Row="1" Content="Country"
HorizontalAlignment="Left" VerticalAlignment="Center"
HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Center" Width="auto" FontSize="16" FontFamily="Century Gothic" FontStretch="Expanded" Height="37" Foreground="#FF464646"/>
<ComboBox HorizontalAlignment="Right" VerticalAlignment="Center"
VerticalContentAlignment="Center" HorizontalContentAlignment="Left"
Height="23" Width="135"
ItemsSource="{Binding Countries}"
DisplayMemberPath="Name" SelectedValuePath="Country_ID"
SelectedValue="{Binding CurrentAddress.Country_id}"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Height="Auto"
VerticalAlignment="Top" Margin="35,304,10,-13">
<Label Grid.Row="1" Content="Region"
HorizontalAlignment="Left" VerticalAlignment="Center"
HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Center" Width="auto" FontSize="16" FontFamily="Century Gothic" FontStretch="Expanded" Height="37" Foreground="#FF464646"/>
<ComboBox HorizontalAlignment="Right" VerticalAlignment="Center"
VerticalContentAlignment="Center" HorizontalContentAlignment="Left"
Height="23" Width="135" ItemsSource="{Binding Zones}"
DisplayMemberPath="Name" SelectedValuePath="Zone_ID"
SelectedValue="{Binding CurrentAddress.Zone_id}"/>
</StackPanel>
</Grid>
</GroupBox>
<GroupBox Header="Otro" FontFamily="Century gothic" Height="auto" Width="Auto"
VerticalAlignment="Top" VerticalContentAlignment="Top">
<Grid Margin="0">
<StackPanel Orientation="Vertical"
VerticalAlignment="Top" Margin="10">
<CheckBox HorizontalAlignment="Center" Style="{DynamicResource CheckBoxSlider}"
VerticalAlignment="Center" Content="Newsletter" FontSize="16" FontStretch="Expanded"
FontFamily="Century Gothic" Foreground="#FF464646" VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch" Width="255" Margin="30,8"
IsChecked="{Binding CurrentCustomer.Newsletter}"/>
<CheckBox HorizontalAlignment="Center" Style="{DynamicResource CheckBoxSlider}"
VerticalAlignment="Center" Content="Status" FontSize="16" FontStretch="Expanded"
FontFamily="Century Gothic" Foreground="#FF464646" VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch" Width="255" Margin="10,8"
IsChecked="{Binding CurrentCustomer.Status}"/>
<CheckBox HorizontalAlignment="Center" Style="{DynamicResource CheckBoxSlider}"
VerticalAlignment="Center" Content="Safe" FontSize="16" FontStretch="Expanded"
FontFamily="Century Gothic" Foreground="#FF464646" VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch" Width="255" Margin="10,8"
IsChecked="{Binding CurrentCustomer.Safe}"/>
</StackPanel>
</Grid>
</GroupBox>
</WrapPanel>
</ScrollViewer>
<Button Content="Accept" Grid.Row="2" Height="30"
VerticalAlignment="Bottom" HorizontalAlignment="Right"
Width="80" Margin="0,0,10,10"
Command="{Binding SaveCommand}"/>
</Grid>