ListView 和 TextBox OnPropertyChanged 工作正常但 Tab Control 不工作

问题描述 投票:0回答:0

过去几周,当我更改列表视图文本框中的值时,我努力解决在选项卡控件中进行更改的问题,反之亦然。

一切都适用于列表视图和文本框,但当我更改选项卡控件中的值时,我无法完成这项工作,该值会在列表视图中自动更改。有人可以帮我解决这个问题吗,谢谢。

这是我的代码模型

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)
);
wpf listview mvvm tabcontrol
© www.soinside.com 2019 - 2024. All rights reserved.