Я новичок в 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;
};
}
}
}