WPF передает параметры от страницы к странице - PullRequest
0 голосов
/ 18 октября 2019

Я новичок в WPF . В приведенном ниже коде я хочу перейти с одной страницы на другую с передачей аргументов. Я хочу сделать все в стиле MVVM . Поэтому я нажимаю на элемент в списке на странице MainPage.xaml и перехожу на страницу EmployeeDetailsPage.xaml , где я вижу детали записи. Есть ли способ улучшить или упростить эту функцию (лучше и проще:))?

Я подготовил одно окно навигации и 2 страницы.

MainWindow.xaml

<NavigationWindow x:Class="WpfApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp"
        xmlns:viewModel="clr-namespace:WpfApp.ViewModels"          
        mc:Ignorable="d"
       Title="MainWindow" Height="450" Width="800" Source="/Pages/MainPage.xaml" ShowsNavigationUI="False">
    <NavigationWindow.DataContext>
        <viewModel:PeopleViewModel></viewModel:PeopleViewModel>
    </NavigationWindow.DataContext>
</NavigationWindow>

MainPage.xaml

<Page x:Class="WpfApp.Pages.MainPage"
      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:local="clr-namespace:WpfApp.Pages"
      xmlns:employeeVM="clr-namespace:WpfApp.ViewModels"
      xmlns:employeeList="clr-namespace:WpfApp.ViewModels"
      xmlns:commands="clr-namespace:WpfApp.Commands"
      xmlns:converters="clr-namespace:WpfApp.Converters"
      mc:Ignorable="d" 
      d:DesignHeight="450" d:DesignWidth="800"
      Title="MainPage">


    <Page.Resources>
        <ResourceDictionary>
            <commands:SetSelectedCommand x:Name="SetSelected" x:Key="SetSelectedItem"></commands:SetSelectedCommand>
            <converters:SetSelectedConverter x:Name="SetSelectedConverter" x:Key="SetSelectedItemConverter"></converters:SetSelectedConverter>
        </ResourceDictionary>
    </Page.Resources>

    <Grid>

        <StackPanel>

            <ListBox ItemsSource="{Binding Path=EmployeeList}" x:Name="list">
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal">
                            <TextBlock Width="100" Text="{Binding Path=FirstName}"></TextBlock>
                            <TextBlock Width="100" Margin="2,0,0,0" Text="{Binding Path=LastName}"></TextBlock>
                            <TextBlock Width="100" Margin="2,0,0,0" Text="{Binding Path=Company}"></TextBlock>
                            <TextBlock VerticalAlignment="Stretch" HorizontalAlignment="Right" Margin="6,0,0,0" FontSize="10" Padding="4">
                                <Hyperlink Tag="{Binding Path=Id}" Command="{Binding Source={StaticResource SetSelectedItem}}" NavigateUri="/Pages/EmployeeDetailsPage.xaml">
                                    <Hyperlink.CommandParameter>
                                        <MultiBinding Converter="{StaticResource SetSelectedItemConverter}">
                                            <Binding RelativeSource="{RelativeSource Self}" />
                                            <Binding RelativeSource="{RelativeSource AncestorType={x:Type local:MainPage}}"></Binding>
                                        </MultiBinding>
                                    </Hyperlink.CommandParameter>
                                    Zobacz
                                </Hyperlink>
                            </TextBlock>

                        </StackPanel>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>

        </StackPanel>

    </Grid>
</Page>

EmployeeDetailsPage.xaml

<Page x:Class="WpfApp.Pages.EmployeeDetailsPage"
      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:local="clr-namespace:WpfApp.Pages"
      xmlns:employeeVM="clr-namespace:WpfApp.ViewModels"
      xmlns:employeeList="clr-namespace:WpfApp.ViewModels"
      mc:Ignorable="d" 
      d:DesignHeight="450" d:DesignWidth="800"
      Title="EmployeeDetailsPage">


    <Grid>

        <Grid.ColumnDefinitions>
            <ColumnDefinition></ColumnDefinition>
        </Grid.ColumnDefinitions>

        <Grid.RowDefinitions>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
        </Grid.RowDefinitions>

        <StackPanel Grid.Row="0" Margin="10">
            <Label>Employee details</Label>
            <TextBlock Text="{Binding Id}"></TextBlock>
            <TextBlock Text="{Binding LastName}"></TextBlock>
            <TextBlock Text="{Binding FirstName}"></TextBlock>
            <TextBlock Text="{Binding Company}"></TextBlock>
        </StackPanel>


        <StackPanel Grid.Row="1" Margin="10">
            <TextBlock>
                <Hyperlink NavigateUri="/Pages/MainPage.xaml">Back to list</Hyperlink>
            </TextBlock>
        </StackPanel>

    </Grid>
</Page>

EmployeeViewModel.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WpfApp.Models;

namespace WpfApp.ViewModels
{
    public class EmployeeViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        private int _id;
        private string _firstName;
        private string _lastName;
        private string _company;
        private bool _selected;

        public int Id
        {
            get => _id;
            set
            {
                if (value != _id)
                {
                    _id = value;
                    OnPropertyChanged("Id");
                }
            }
        }

        public bool Selected
        {
            get => _selected;
            set
            {
                if (value != _selected)
                {
                    _selected = value;
                    OnPropertyChanged("Selected");
                }
            }
        }

        public string FirstName 
        {
            get => _firstName;
            set
            {
                if(value != _firstName)
                {
                    _firstName = value;
                    OnPropertyChanged("FirstName");
                }
            } 
        }
        public string LastName
        {
            get => _lastName;
            set
            {
                if (value != _lastName)
                {
                    _lastName = value;
                    OnPropertyChanged("LastName");
                }
            }
        }
        public string Company
        {
            get => _company;
            set
            {
                if (value != _company)
                {
                    _company = value;
                    OnPropertyChanged("Company");
                }
            }
        }


        private void OnPropertyChanged(string propName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
        }

    }
}

PeopleViewModel.cs

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls;

namespace WpfApp.ViewModels
{
    public class PeopleViewModel
    {
        public ObservableCollection<EmployeeViewModel> EmployeeList { get; set; } = new ObservableCollection<EmployeeViewModel>();

        public ListBoxItem Selected { get; set; }
        public PeopleViewModel()
        {
            EmployeeList.Add(new EmployeeViewModel { Selected = false, Company = "Sony", FirstName = "Kamila", LastName = "Kowalska", Id = 1 });
            EmployeeList.Add(new EmployeeViewModel { Selected = false, Company = "IBM", FirstName = "Klaudia", LastName = "Kalinowska", Id = 2 });
            EmployeeList.Add(new EmployeeViewModel { Selected = false, Company = "MSI", FirstName = "Karolina", LastName = "Kuczyńska", Id = 3 });
            EmployeeList.Add(new EmployeeViewModel { Selected = false, Company = "MSI", FirstName = "Kornelia", LastName = "Kamińska", Id = 4 });
            EmployeeList.Add(new EmployeeViewModel { Selected = false, Company = "Hewlett-Packard", FirstName = "Kordelia", LastName = "Kalinowska", Id = 5 });
        }
    }
}


SetSelectedConverter.cs

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Data;

namespace WpfApp.Converters
{
    public class SetSelectedConverter : IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            return values.Clone();
        }

        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
        {
            return new object[2];
        }
    }
}

SetSelectedCommand.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using WpfApp.ViewModels;

namespace WpfApp.Commands
{
    public class SetSelectedCommand : ICommand
    {
        public event EventHandler CanExecuteChanged;

        public bool CanExecute(object parameter)
        {
            return true;
        }

        public void Execute(object parameter)
        {
            var parameters = parameter as object[];
            var link = parameters[0] as Hyperlink;
            var page = parameters[1] as Page;
            var id = int.Parse(link.Tag.ToString());
            var pvm = page.DataContext as PeopleViewModel;
            var selected = pvm.EmployeeList.FirstOrDefault(e => e.Id == id);

            foreach (var item in pvm.EmployeeList)
            {
                item.Selected = false;
            }

            if(selected != null)
            {
                selected.Selected = true;
            }

        }
    }
}

EmployeeDetailsPage.xaml.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using WpfApp.ViewModels;

namespace WpfApp.Pages
{

    public partial class EmployeeDetailsPage : Page
    {
        public EmployeeDetailsPage()
        {
            InitializeComponent();

            Initialized += (s, a) =>
            {

            };
            this.Loaded += (s, a) =>
            {
                var ctx = DataContext;
                var list = ctx as PeopleViewModel;
                var selected = list.EmployeeList.First(e => e.Selected);
                DataContext = selected;
            };
        }
    }
}


...