当我在 WPF(.NET Core)中单击第二个窗口的“确定”按钮时,禁用 MainWindow 按钮并返回到 MainWindow 的初始状态

Posted

技术标签:

【中文标题】当我在 WPF(.NET Core)中单击第二个窗口的“确定”按钮时,禁用 MainWindow 按钮并返回到 MainWindow 的初始状态【英文标题】:Disable button of MainWindow and return to the initial state of MainWindow when I click an "OK" button of a Second Window in WPF (.NET Core) 【发布时间】:2021-01-09 09:09:30 【问题描述】:

我在 WPF 应用程序中有两个窗口。第一个是 MainWindow,而第二个是 SecondaryWindow,它在 MainWindow 中填充数据。

简而言之,我的 MainWindow 中有一个“加载”按钮,该按钮被禁用,只有在用户浏览本地文件时才会启用。启用“加载”后,会要求用户填写一些凭据以将数据加载到 SQL Server 中的表中。当用户在第二个窗口中单击“确定”时,我希望 MainWindow 返回其初始状态。

MainWindow.xaml.cs 文件

using MaterialDesignThemes.Wpf;
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 System.Data.SqlClient;
using System.Diagnostics;
using System.Data;
using System.IO;

namespace TestEnvironment

    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    
    public static class StringExtensions
    
        public static string Args(this string str, params object[] args)
        
            return String.Format(str, args);
        
    

    public partial class MainWindow : Window
    
        public MainWindow()
        
            InitializeComponent();
        

        // Functions - Methods

        public DataTable ConvertToDataTable(string filePath)
        
            DataTable tbl = new DataTable();

            // Take the first 10 lines
            var lines = File.ReadLines(filePath).Take(10);

            // Split each line and create an integer sequence where each value 
            // is the number of the splitted elements
            // then get the max value present in this sequence
            var max = lines.Select(x => x.Split('\t').Length).Max();

            // First line contains headers
            string[] headers = lines.First().Split('\t');

            // Now create the table with the max number of columns present
            for (int col = 0; col < max; col++)
                tbl.Columns.Add(headers[col], typeof(string));

            //Use the Rows.Add method that accepts an object array
            foreach (string line in lines.Skip(1))
            

                tbl.Rows.Add(line.Split('\t'));

            

            //UTF-8 encoding

            /*var utf8 = Encoding.UTF8;

            foreach (string line in lines.Skip(1))
            
                IEnumerable<string> utf8Values = line.Split('\t')
                    .Select(s => utf8.GetString(Encoding.Convert(Encoding.ASCII, utf8,
                        Encoding.ASCII.GetBytes(s))));
                tbl.Rows.Add(utf8Values);
            */

            /*foreach (DataRow dr in tbl.Rows)
            

                Debug.WriteLine(dr["Nationality"]);

                string s = dr["Nationality"].ToString();

                byte[] bytes = Encoding.Default.GetBytes(s);
                dr["Nationality"] = Encoding.UTF8.GetString(bytes);

                Debug.WriteLine(dr["Nationality"]);
            */

            return tbl;
        

        public static void WriteDataToFile(DataTable submittedDataTable, string submittedFilePath)
        
            int i = 0;
            StreamWriter sw = null;

            sw = new StreamWriter(submittedFilePath, false);

            for (i = 0; i < submittedDataTable.Columns.Count - 1; i++)
            

                sw.Write(submittedDataTable.Columns[i].ColumnName + ";");

            
            sw.Write(submittedDataTable.Columns[i].ColumnName);
            sw.WriteLine();

            foreach (DataRow row in submittedDataTable.Rows)
            
                object[] array = row.ItemArray;

                for (i = 0; i < array.Length - 1; i++)
                
                    sw.Write(array[i].ToString() + ";");
                
                sw.Write(array[i].ToString());
                sw.WriteLine();

            

            sw.Close();
        

        public static void SubmitData(string connectionString, string tablenametext)
        
            using (SqlConnection sqlConnection = new SqlConnection(connectionString))
            
                sqlConnection.Open();
                using (var command = sqlConnection.CreateCommand())
                
                    command.CommandType = CommandType.StoredProcedure;
                    command.CommandText = "createselectedtableinDB";
                    command.Parameters.AddWithValue("@TableName", tablenametext);
                    command.ExecuteNonQuery();
                
            
        

        public static string CreateConnectionString(string servernametext, string databasenametext)
        
            string connectionstring = "Server=0;Database=1;Integrated Security=SSPI".Args(servernametext, databasenametext);

            return connectionstring;
        

        // Object Interactions

        private void BrowseButton_Click(object sender, RoutedEventArgs e)
           

            // Create OpenFileDialog
            Microsoft.Win32.OpenFileDialog openFileDlg = new Microsoft.Win32.OpenFileDialog();

            // Launch OpenFileDialog by calling ShowDialog method
            Nullable<bool> result = openFileDlg.ShowDialog();
            // Get the selected file name and display in a TextBox.
            // Load content of file in a TextBlock
            if (result == true)
            
                FileNameTextBox.Text = openFileDlg.FileName;
                TextBlock1.Text = "Created on: " + File.GetCreationTime(openFileDlg.FileName).ToString() +"\n";
                
                Debug.WriteLine(File.GetCreationTime(openFileDlg.FileName).ToString());
                
                var datatablematrix = ConvertToDataTable(filePath: openFileDlg.FileName);

                /*Debug.WriteLine(datatablematrix);

                WriteDataToFile(datatablematrix, @"C:\Users\spano\Desktop\ApplicationOption2\testdummy.txt");*/

                grid.DataContext = datatablematrix.DefaultView;

            

            // Set filter for file extension and default file extension  
            openFileDlg.DefaultExt = ".txt";
            openFileDlg.Filter = "Text files (*.txt)|*.txt|All files (*.*)|*.*";

            Debug.WriteLine("Txt imported");

            // Set initial directory    
            openFileDlg.InitialDirectory = @"C:\Documents\";

            // Multiple selection with all file types    
            openFileDlg.Multiselect = true;

            BrowseButton.IsEnabled = true;
            LoadButton.IsEnabled = true;

            Debug.WriteLine("End!");

        

        private void LoadButton_Click(object sender, RoutedEventArgs e)
        
            TableNamePopupwindow popup = new TableNamePopupwindow();
            //ShowDialog means you can't focus the parent window, only the popup
            popup.ShowDialog(); //execution will block here in this method until the popup closes
            
            string resultTable = popup.TableNameValue;
            string resultServer = popup.ServerNameValue;
            string resultDatabase = popup.DatabaseNameValue;

            var connectionString = CreateConnectionString(resultServer, resultDatabase);

            SubmitData(connectionString, resultTable);

        

        private void PowerButton_Click(object sender, RoutedEventArgs e)
        
            App.Current.Shutdown();
        

        private void MinimizeButton_Click(object sender, RoutedEventArgs e)
        
            this.WindowState = WindowState.Minimized;
        

        private void TabablzControl_SelectionChanged(object sender, SelectionChangedEventArgs e)
        

        
    


TableNamePopupwindow.xaml.cs

using MaterialDesignThemes.Wpf;
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 System.Data.SqlClient;
using System.Diagnostics;
using System.Data;
using System.IO;

namespace TestEnvironment

    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>

    public partial class TableNamePopupwindow : Window

    
        public string TableNameValue

        
           get
            
                if (TableName == null) return string.Empty;

                return TableName.Text;
            
        

        public string ServerNameValue

        
            get
            
                if (ServerName == null) return string.Empty;

                return ServerName.Text;
            
        

        public string DatabaseNameValue

        
            get
            
                if (DatabaseName == null) return string.Empty;

                return DatabaseName.Text;
            
        

        public TableNamePopupwindow()
        
            InitializeComponent();
        

        private void OnOk_Click(object sender, RoutedEventArgs e)
           
            //code I found here: https://***.com/questions/46089017/wpf-passing-text-from-one-window-to-another-window
            MainWindow mainWindow = new MainWindow();
            mainWindow.Show();
            mainWindow.LoadButton.IsEnabled = false;
            this.Close();
        
    


正如您在上面看到的 OnOK 单击我希望重新禁用“加载按钮”。

MainWindow 的屏幕截图(用户打开应用时的初始状态)

MainWindow 的屏幕截图(用户浏览文件)

SecondWindow 的屏幕截图(当用户点击“加载”按钮时)

我想要的是当用户单击“确定”按钮关闭第二个窗口时 MainWindow 返回其初始状态(附上第一个屏幕截图)。 根据我在SO question 上找到的第二个窗口的代码,我设法返回初始状态,但每次单击“确定”按钮时都会打开一个新的 MainWindow。

【问题讨论】:

您解决了encoding 问题吗? @mm8 还没有。如果您想了解有关我发布的 SO 问题的更多信息,请通知我,因为我不确定我提供的材料是否足够。 您的问题是如何在MainWindow 中设置ButtonIsEnabled 属性? @mm8 是的,实际上这是我尝试过的,但没有运气。我希望当用户浏览文件并加载文件后,再次禁用“加载”按钮并清除 DataGrid 中的数据(如我上传的第一个屏幕截图)。所以它就像一个循环 Screenshot 1->2->3->1 【参考方案1】:

与其在OnOk_Click 处理程序中打开MainWindow 的新实例,不如修改已经存在并打开的实例。

您需要以某种方式获得对它的引用。例如,您可以在打开 TableNamePopupwindow 时将其注入引用:

private readonly MainWindow _mainWindow;

public TableNamePopupwindow(MainWindow mainWindow)

    InitializeComponent();
    _mainWindow = mainWindow;


private void OnOk_Click(object sender, RoutedEventArgs e)

    _mainWindow.LoadButton.IsEnabled = false;
    this.Close();

主窗口:

TableNamePopupwindow popup = new TableNamePopupwindow(this);
popup.ShowDialog();

【讨论】:

以上是关于当我在 WPF(.NET Core)中单击第二个窗口的“确定”按钮时,禁用 MainWindow 按钮并返回到 MainWindow 的初始状态的主要内容,如果未能解决你的问题,请参考以下文章

WPF 数据绑定到第二个视图

如何在 WPF .NET Core 应用程序中启用控制台?

如何以编程方式水平平铺某些窗口?

单击已显示键盘的第二个UITextField会错误地移动内容

WPF延迟选择中的组合框

敲除加载和保存视图模型