过去几周,当我更改列表视图文本框中的值时,我努力解决在选项卡控件中进行更改的问题,反之亦然。
一切都适用于列表视图和文本框,但当我更改选项卡控件中的值时,我无法完成这项工作,该值会在列表视图中自动更改。有人可以帮我解决这个问题吗,谢谢。
namespace TabStudents.Models
{
public class StudentsModel
{
public int Id { get; set; }
public string FullName { get; set; } = null!;
public string FirstName { get; set; } = null!;
public string LastName { get; set; } = null!;
}
}
学生资料库
namespace TabStudents.Repository
{
public class StudentsRepository
{
public readonly ObservableCollection<StudentsModel> students;
public IEnumerable<StudentsModel> Peoples
{
get { return students; }
}
public StudentsRepository()
{
students = new ObservableCollection<StudentsModel>();
try
{
CRUD.con.Open();
CRUD.adp = new NpgsqlDataAdapter("SELECT CONCAT(firstname, ' ', lastname) AS full_name, " +
"id, firstname, lastname,TO_CHAR(dob,'dd.MM.yyyy.') dob FROM students ORDER BY firstname ", CRUD.con);
DataTable dt = new DataTable();
CRUD.adp.Fill(dt);
foreach (DataRow row in dt.Rows)
{
students.Add(new StudentsModel()
{
Id = (int)row["id"],
FullName = (string)row["full_name"],
FirstName = (string)row["firstname"],
LastName = (string)row["lastname"]
});
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
CRUD.con.Close();
}
}
public bool Add(StudentsModel student)
{
if (students.IndexOf(student) < 0)
{
students.Add(student);
return true;
}
return false;
}
public bool Remove(StudentsModel osobeModel)
{
if (students.IndexOf(osobeModel) >= 0)
{
students.Remove(osobeModel);
return true;
}
return false;
}
private static string GetValueOrDefault(XContainer el, string propertyName)
{
return el.Element(propertyName) == null ? string.Empty : el.Element(propertyName).Value;
}
}
}
主视图模型
namespace TabStudents.ViewModels
{
public partial class MainViewModel : ObservableObject
{
public IEnumerable<StudentsModel> Peoples => _studentsRepository.Peoples;
public ObservableCollection<StudentsDetailViewModel> Tabs { get; } = new();
private ObservableCollection<StudentsDetailViewModel> _items = new ObservableCollection<StudentsDetailViewModel>();
private StudentsRepository _studentsRepository;
[ObservableProperty]
[NotifyCanExecuteChangedFor(nameof(RemoveCommand))]
private StudentsModel _selectedStudent;
[ObservableProperty]
private string _idd;
[ObservableProperty]
private string _firstNamee;
[ObservableProperty]
private string _lastNamee;
public MainViewModel(StudentsRepository studentsRepository)
{
_studentsRepository = studentsRepository ??
throw new ArgumentNullException("studentsRepository");
}
//private bool HasSelectedCustomer() => SelectedCustomer != null;
private bool _hasSelectedStudent;
public bool HasSelectedStudent
{
get
{
if (SelectedStudent != null)
{
FirstNamee = SelectedStudent.FirstName;
LastNamee = SelectedStudent.LastName;
StudentsDetailViewModel newTab;
newTab = new StudentsDetailViewModel(SelectedStudent)
{
Title = $"{FirstNamee + " " + LastNamee}"
};
Tabs.Add(newTab);
this.CurrentPage = newTab;
}
return _hasSelectedStudent;
}
}
private StudentsDetailViewModel _currentPage;
public StudentsDetailViewModel CurrentPage
{
get { return _currentPage; }
set
{
_currentPage = value;
if (!_items.Contains(value))
{
_items.Add(value);
}
OnPropertyChanged(nameof(CurrentPage));
}
}
[RelayCommand]
private void CloseTab(StudentsDetailViewModel obj)
{
Tabs.Remove(obj);
}
[RelayCommand]
private void Add()
{
var studentsModel = new StudentsModel();
_studentsRepository.Add(studentsModel);
SelectedStudent = studentsModel;
OnPropertyChanged("StudentsModel");
}
[RelayCommand(CanExecute = "HasSelectedStudent")]
private void Remove()
{
if (SelectedStudent != null)
{
_studentsRepository.Remove(SelectedStudent);
SelectedStudent = null;
OnPropertyChanged("StudentsModel");
}
}
[RelayCommand]
private void Save()
{
// _customerRepository.Commit();
}
[RelayCommand]
private void Search(string textToSearch)
{
var coll = CollectionViewSource.GetDefaultView(Peoples);
if (!string.IsNullOrWhiteSpace(textToSearch))
coll.Filter = c => ((StudentsModel)c).LastName.ToLower().Contains(textToSearch.ToLower());
else
coll.Filter = null;
}
}
}
StudentsDetailViewModel
namespace TabStudents.ViewModels
{
public partial class StudentsDetailViewModel : ObservableObject
{
[ObservableProperty]
private string _title = string.Empty;
[ObservableProperty]
private StudentsModel _student;
[ObservableProperty]
private string _idd;
[ObservableProperty]
private string _firstNamee;
[ObservableProperty]
private string _lastNamee;
public StudentsDetailViewModel(StudentsModel tabs)
{
if (tabs == null)
throw new ArgumentNullException("student");
_student = tabs;
Idd = _student.Id.ToString();
FirstNamee = _student.FirstName;
LastNamee = _student.LastName;
}
}
}
主窗口
<Window x:Class="TabStudents.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:stu="clr-namespace:TabStudents"
xmlns:vm="clr-namespace:TabStudents.ViewModels"
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
xmlns:view="clr-namespace:TabStudents.Views"
Title="MainWindow" Height="500" Width="800">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="40" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="100" />
<RowDefinition Height="50" />
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Last Name" VerticalAlignment="Center" Margin="5"/>
<TextBox x:Name="searchText" VerticalAlignment="Center" Margin="5,3" Width="250" Height="25" VerticalContentAlignment="Center"/>
<Button x:Name="PesqBtn" Content="Find" Width="75" Height="25" Margin="10,5" VerticalAlignment="Center"
Command="{Binding SearchCommand}" CommandParameter="{Binding ElementName=searchText,Path=Text}"/>
</StackPanel>
<DataGrid AutoGenerateColumns="False" x:Name="master" CanUserAddRows="False" CanUserDeleteRows="True" Grid.Row="1"
ItemsSource="{Binding Peoples}" SelectedItem="{Binding SelectedStudent, Mode=TwoWay}">
<DataGrid.Columns >
<DataGridTextColumn Binding="{Binding Path=Id}" Header="Id" Width="60" />
<DataGridTextColumn Binding="{Binding Path=FirstName}" Header="First Name" Width="160" />
<DataGridTextColumn Binding="{Binding Path=LastName}" Header="Last Name" Width="160" />
</DataGrid.Columns>
</DataGrid>
<TabControl Grid.Row="3" ItemsSource="{Binding Tabs}"
SelectedItem="{Binding SelectedStudent, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" >
<TabControl.Resources>
<DataTemplate DataType="{x:Type vm:StudentsDetailViewModel}">
<view:StudentsDetailView />
</DataTemplate>
</TabControl.Resources>
<TabControl.ItemTemplate>
<DataTemplate DataType="{x:Type vm:StudentsDetailViewModel}">
<DockPanel MinWidth="100">
<Button Content="X" Cursor="Hand" DockPanel.Dock="Right"
Command="{Binding DataContext.CloseTabCommand, RelativeSource={RelativeSource FindAncestor, AncestorType=TabControl}}"
CommandParameter="{Binding }"/>
<TextBlock Text="{Binding Title}" />
</DockPanel>
</DataTemplate>
</TabControl.ItemTemplate>
</TabControl>
<stu:StudentsView Grid.Row="2" DataContext="{Binding SelectedStudent}" Margin="5" />
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Margin="5" Grid.Row="4">
<Button Width="75" Height="25" Margin="5" Content="Add" Command="{Binding AddCommand}" />
<Button Width="75" Height="25" Margin="5" Content="Remove" Command="{Binding RemoveCommand}" />
<Button Width="75" Height="25" Margin="5" Content="Save" Command="{Binding SaveCommand}" />
</StackPanel>
</Grid>
StudentsDetailView
<UserControl x:Class="TabStudents.Views.StudentsDetailView"
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:TabStudents.Views"
xmlns:vm="clr-namespace:TabStudents.ViewModels"
mc:Ignorable="d" d:DataContext="{x:Type vm:StudentsDetailViewModel}">
<Grid x:Name="LayoutRoot" Background="White" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!-- First Name -->
<Label Content="First Name:"
HorizontalAlignment="Right" Padding="0,0,2,0" Grid.Column="0" Grid.Row="0"/>
<TextBox Text="{Binding Path=FirstNamee, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" Grid.Column="1" Grid.Row="0">
<TextBox.Resources>
<Style TargetType="{x:Type Border}">
<Setter Property="CornerRadius" Value="3"/>
</Style>
</TextBox.Resources>
</TextBox>
<!-- Last Name -->
<Label Content="Last Nmae:" HorizontalAlignment="Right" Padding="0" Grid.Column="0" Grid.Row="1"/>
<TextBox Text="{Binding LastNamee}" Grid.Column="1" Grid.Row="1">
<TextBox.Resources>
<Style TargetType="{x:Type Border}">
<Setter Property="CornerRadius" Value="3"/>
</Style>
</TextBox.Resources>
</TextBox>
</Grid>
学生看
<UserControl x:Class="TabStudents.StudentsView"
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"
mc:Ignorable="d"
d:DesignHeight="421" d:DesignWidth="531" x:Name="detailControl">
<Grid DataContext="{Binding ElementName=detailControl, Path=DataContext}">
<Grid Name="grid1" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Label Content="Id:" Grid.Column="0" Grid.Row="0" Margin="1" VerticalAlignment="Center" />
<TextBox Grid.Column="1" Grid.Row="0" Margin="3" Text="{Binding Path=Id, Mode=TwoWay, ValidatesOnExceptions=true, NotifyOnValidationError=true}" VerticalAlignment="Center" />
<Label Content="First Name:" Grid.Column="0" Grid.Row="1" Margin="1" VerticalAlignment="Center" />
<TextBox Grid.Column="1" Grid.Row="1" Margin="3" Text="{Binding Path=FirstName, Mode=TwoWay, ValidatesOnExceptions=true, NotifyOnValidationError=true}" VerticalAlignment="Center" />
<Label Content="Last Name:" Grid.Column="0" Grid.Row="2" Margin="1" VerticalAlignment="Center" />
<TextBox Grid.Column="1" Grid.Row="2" Margin="3" Text="{Binding Path=LastName, Mode=TwoWay, ValidatesOnExceptions=true, NotifyOnValidationError=true}" VerticalAlignment="Center" />
</Grid>
</Grid>
</UserControl>
连接到 PostgreSQL 数据库
using Npgsql;
using System;
using System.Configuration;
using System.Data;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using System.Windows;
namespace TabStudents
{
public class CRUD
{
public static string passw = "yourpassword";
public static string GetConnectionString()
{
string host = "Server=localhost;";
string port = "Port=5432;";
string db = "Database=students;";
string user = "Username=postgres;";
string pass = "Password=" + passw + ";";
string conString = String.Format("{0}{1}{2}{3}{4}", host, port, db, user, pass);
return conString;
}
public static NpgsqlConnection con = new NpgsqlConnection(GetConnectionString());
public static NpgsqlCommand cmd = default;
public static string sql = string.Empty;
public static NpgsqlDataAdapter adp = new NpgsqlDataAdapter();
public static DataTable PerformCRUD(NpgsqlCommand com)
{
DataTable dt = new DataTable();
try
{
NpgsqlDataAdapter da = new NpgsqlDataAdapter
{
SelectCommand = com
};
da.Fill(dt);
return dt;
}
catch (Exception ex)
{
MessageBox.Show("Error" + ex.Message, "Error",
MessageBoxButton.OK, MessageBoxImage.Error);
dt = null;
}
return dt;
}
}
}
--表:public.students
CREATE TABLE public.students (
id serial NOT NULL,
firstname varchar(50),
lastname varchar(50),
dob date,
/* Keys */
CONSTRAINT students_pkey
PRIMARY KEY (id)
);