Я видел, как вы спрашивали о том, как работать с этим, позвольте мне показать вам один способ, надеюсь, это поможет, но я рекомендую вам прочитать о шаблонах и инфраструктурах MVVM , таких как MVVMLight для WPF.
Ну, для этого сначала нужно установить Install-Package MvvmLight -Version 5.4.1
Тогда вам может понадобиться исправить одну проблему с ссылками, в ViewModelLocator удалите все употребления и замените на:
using GalaSoft.MvvmLight.Ioc;
using CommonServiceLocator;
Теперь ваш MainWindowView.xaml
должен выглядеть так:
<Window x:Class="WpfApp2.MainWindow"
x:Name="root"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="clr-namespace:WpfApp2.ViewModel"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.DataContext>
<vm:MainViewModel x:Name="Model"/>
</Window.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<DataGrid AutoGenerateColumns="False" x:Name="userDataGrid" Margin="70,0.2,70,0" ItemsSource="{Binding Users}">
<DataGrid.Columns>
<DataGridTextColumn Header="ID" Binding="{Binding UserId}"/>
<DataGridTextColumn Header="Username" Binding="{Binding UserName}"/>
<DataGridTextColumn Header="Email" Binding="{Binding UserEmail}"/>
<DataGridTextColumn Header="User Role" Binding="{Binding UserRole}"/>
<DataGridTextColumn Header="Created Date" Binding="{Binding UserCreatedDate}"/>
</DataGrid.Columns>
<DataGrid.RowDetailsTemplate>
<DataTemplate>
<Border BorderThickness="0" Background="BlanchedAlmond" Padding="10">
<StackPanel Orientation="Vertical">
<StackPanel Orientation="Horizontal">
<TextBlock FontSize="12" Text="User ID: " VerticalAlignment="Center" />
<TextBlock x:Name="txtBlockId" FontSize="16" Foreground="MidnightBlue" Text="{Binding UserId, Mode=TwoWay}" VerticalAlignment="Center" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock FontSize="12" Text="First Name: " VerticalAlignment="Center" />
<TextBox x:Name="txtFirstName" FontSize="16" Foreground="MidnightBlue" Text="{Binding UserFirstName, Mode=TwoWay}" VerticalAlignment="Center" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock FontSize="12" Text="Last Name: " VerticalAlignment="Center" />
<TextBox x:Name="txtLastName" FontSize="16" Foreground="MidnightBlue" Text="{Binding UserLastName}" VerticalAlignment="Center" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock FontSize="12" Text="User Role: " VerticalAlignment="Center" />
<ComboBox ItemsSource="{Binding Path=DataContext.UserRoles, ElementName=root}" SelectionChanged='CbUserRole_OnSelectionChanged' SelectedItem="{Binding UserRole}" x:Name="cbUserRole" FlowDirection="LeftToRight" FontSize="16" Foreground="MidnightBlue" HorizontalAlignment="Stretch" VerticalAlignment="Center" />
</StackPanel>
<StackPanel>
<Button x:Name="btnUpdate" Content="Update" VerticalAlignment="Center" HorizontalAlignment="Right" Command="{Binding UpdateCommand, ElementName=Model}" CommandParameter="{Binding}" />
</StackPanel>
</StackPanel>
</Border>
</DataTemplate>
</DataGrid.RowDetailsTemplate>
</DataGrid>
</Grid>
</Window>
Тогда в вашем code-behind
есть небольшая обработка событий, которую необходимо выполнить при смене ролей,
using System.Windows;
using System.Windows.Controls;
using WpfApp2.ViewModel;
namespace WpfApp2
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
public MainViewModel ViewModel => (MainViewModel) DataContext;
private void CbUserRole_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
{
ComboBox cb = (ComboBox)sender;
if (cb != null)
{
ViewModel.SelectedUserRole = (UserRole)cb.SelectedItem;
}
}
}
}
Затем вы должны создать ViewModel, например, так: (ViewModel -> MainViewModel.cs
):
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Runtime.CompilerServices;
using GalaSoft.MvvmLight.Command;
using WpfApp2.Data;
namespace WpfApp2.ViewModel
{
public class MainViewModel : INotifyPropertyChanged
{
public MainViewModel()
{
PopulateUserTestData();
UpdateCommand = new RelayCommand<User>(UpdateUser);
}
private ObservableCollection<User> _users;
public ObservableCollection<User> Users
{
get => _users;
set
{
if (_users != value)
{
_users = value;
NotifyPropertyChanged();
}
}
}
private UserRole _userRole;
public UserRole SelectedUserRole
{
get => _userRole;
set
{
if (_userRole != value)
{
_userRole = value;
NotifyPropertyChanged();
}
}
}
public RelayCommand<User> UpdateCommand { get; }
public IEnumerable<UserRole> UserRoles => Enum.GetValues(typeof(UserRole)).Cast<UserRole>();
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void NotifyPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
private void UpdateUser(User user)
{
Users.Single(u => u.UserId == user.UserId).UserRole = SelectedUserRole;
// Do updates on your context (or in-memory).
PrintUsersOnDebug();
}
#region Test data and diagnostics support
private void PrintUsersOnDebug()
{
foreach (User user in Users)
{
Debug.WriteLine("Username: " + user.UserName + " Role: " + user.UserRole);
}
}
private void PopulateUserTestData()
{
Users = new ObservableCollection<User>
{
new User
{
UserId = 1,
UserCreatedDate = DateTime.Now,
UserEmail = "johndoe1@email.com",
UserFirstName = "John",
UserLastName = "Doe",
UserName = "johnd",
UserRole = UserRole.Administrator
},
new User
{
UserId = 2,
UserCreatedDate = DateTime.Now,
UserEmail = "billgordon@email.com",
UserFirstName = "Bill",
UserLastName = "Gordon",
UserName = "billg",
UserRole = UserRole.SuperUser
}
};
PrintUsersOnDebug();
}
#endregion
}
}
Другие родственные классы:
Data->User.cs
using System;
namespace WpfApp2.Data
{
public class User
{
public int UserId { get; set; }
public string UserName { get; set; }
public string UserEmail { get; set; }
public UserRole UserRole { get; set; }
public DateTime UserCreatedDate { get; set; }
public string UserFirstName { get; set; }
public string UserLastName { get; set; }
}
}
UserRole.cs
namespace WpfApp2
{
public enum UserRole
{
Administrator,
User,
SuperUser
}
}
Теперь, так как я только что разработал это тестовое приложение для просмотра изменяющихся данных в этих ролях, я разработал его так, чтобы его можно было просматривать в окне вывода. При изменении ролей и нажатии кнопки обновления проверьте окно вывода.
