MVVM WPF Установка модели для ViewModel - PullRequest
0 голосов
/ 26 сентября 2018

Я занимаюсь разработкой приложения 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>

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...