【问题标题】:WPF handling click event with a databaseWPF 使用数据库处理单击事件
【发布时间】:2016-08-15 11:52:14
【问题描述】:

我现在正在尝试开始使用 WPF。我对 android 和 java 有一些经验,但我从未使用过 C#。我已经建立了一个数据库,我建立了与数据库的连接并使用 LINQ 为数据库 (Visual Studio) 创建了所有的 getter 和 setter,称为 databaselink.dbml。

我创建了一个简单的注册窗口(我知道,密码不应该是纯文本,也不应该存储在变量中,但这只是为了简化应用程序,我无意实际使用它) .

<Window x:Class="Berichtensysteem.Window2"
        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:Berichtensysteem"
        mc:Ignorable="d"
        Title="Registreren" Height="300" Width="300"
        WindowState="Maximized">

    <Grid RenderTransformOrigin="0.494,0.507">

        <TextBox x:Name="username" HorizontalAlignment="Left" Height="23" Margin="144,92,0,0" TextWrapping="Wrap" Text="" VerticalAlignment="Top" Width="120" />
        <TextBox x:Name="password" HorizontalAlignment="Left" Height="23" Margin="144,115,0,0"  VerticalAlignment="Top" Width="120" />
        <TextBox x:Name="passcon" HorizontalAlignment="Left" Height="23" Margin="144,138,0,0" VerticalAlignment="Top" Width="120" />
        <Button x:Name="register" Content="Registreren" HorizontalAlignment="Left" Margin="78,189,0,0" VerticalAlignment="Top" Width="120" Height="23"
        Click="register_click"

                />
        <TextBlock x:Name="usertxt" HorizontalAlignment="Left" Margin="23,93,0,0" Height="23" TextWrapping="Wrap" Text="Gebruikersnaam" VerticalAlignment="Top"/>
        <TextBlock x:Name="pwtxt" HorizontalAlignment="Left" Margin="23,116,0,0" Height="23" TextWrapping="Wrap" Text="Wachtwoord" VerticalAlignment="Top"/>
        <TextBlock x:Name="pwctxt" HorizontalAlignment="Left" Margin="23,138,0,0" Height="23" TextWrapping="Wrap" Text="Herhaal wachtwoord" VerticalAlignment="Top"/>
    </Grid>
</Window>

所以我为我的注册按钮设置了点击。目前,我的代码如下所示:

namespace Berichtensysteem
{
    /// <summary>
    /// Interaction logic for Window2.xaml
    /// </summary>
    public partial class Window2 : Window
    {
        public Window2()
        {
            InitializeComponent();
        }

    private void register_Click(object sender, RoutedEventArgs e)
    {
        if (username.Text.Length == 0)
        {
            username.Text = "Geef gebruikersnaam in";
        }
        else if (password.Text.Length == 0)
        {
            password.Text = "Voer wachtwoord in";
        }
        else if (password != passcon)
        {
            password.Text = "Wachtwoorden niet gelijk";
        }
        else
        {
            string name = username.Text;
            string pass = password.Text;

            // See if user in database exists, add user to database if not.
        }
    }

    }
}

首先,我将窗口重命名为“Registerwindow.xaml”和 Registerwindow.xaml.cs。我的代码没有任何变化,这正常吗?在android中,代码被重构,因为名称必须相同,WPF中不是这样吗?

我的链接类:

#region Extensibility Method Definitions
partial void OnCreated();
partial void Insertemail(email instance);
partial void Updateemail(email instance);
partial void Deleteemail(email instance);
partial void Insertuser(user instance);
partial void Updateuser(user instance);
partial void Deleteuser(user instance);
partial void Inserttype(type instance);
partial void Updatetype(type instance);
partial void Deletetype(type instance);
partial void Insertrecipient(recipient instance);
partial void Updaterecipient(recipient instance);
partial void Deleterecipient(recipient instance);
#endregion

    public databaselinkDataContext() : 
            base(global::Berichtensysteem.Properties.Settings.Default.emaildatabaseConnectionString, mappingSource)
    {
        OnCreated();
    }

    public databaselinkDataContext(string connection) : 
            base(connection, mappingSource)
    {
        OnCreated();
    }

    public databaselinkDataContext(System.Data.IDbConnection connection) : 
            base(connection, mappingSource)
    {
        OnCreated();
    }

    public databaselinkDataContext(string connection, System.Data.Linq.Mapping.MappingSource mappingSource) : 
            base(connection, mappingSource)
    {
        OnCreated();
    }

    public databaselinkDataContext(System.Data.IDbConnection connection, System.Data.Linq.Mapping.MappingSource mappingSource) : 
            base(connection, mappingSource)
    {
        OnCreated();
    }

有人可以帮我解决这个问题吗?如果我有一个示例,我可以继续使用它来完成所有其他与数据库相关的工作。抱歉,如果这看起来很愚蠢。

哦,如果不清楚,我的问题是:我现在如何检查用户是否存在于我的数据库中,如果不存在则添加它。

【问题讨论】:

    标签: c# wpf linq data-binding


    【解决方案1】:

    您的问题似乎不是 WPF 问题,而是与您的数据访问层有关。你会想要对 LinqToSql 做更多的研究,但是为了让你开始。

    else
    {
        string name = username.Text;
        string pass = password.Text;
    
        using (var db = new databaselinkDataContext())
        {
            // x.Id is an example, I don't know the schema of your table.
            var user = db.user.Where(x => x.Id == name).SingleOrDefault();
            if (user == null)
                MessageBox.Show(String.Format("User '{0}' does not exist in the database.", name));
    
            // Again user.Password is an example, I don't know the schema of your table.
            if (user != null && user.Password != pass)
                MessageBox.Show("Password is invalid.");
        }
    }
    

    【讨论】:

    • 谢谢,我现在可以使用了。现在也开始了解更多实际代码,这对我真的很有帮助。谢谢
    【解决方案2】:

    首先,我将窗口重命名为“Registerwindow.xaml”,然后 注册窗口.xaml.cs。我的代码没有任何变化,这正常吗?在 android,代码被重构,因为名称必须是 同样,WPF中不是这样吗?

    文件名与编译的最终结果无关,文件名和内容之间根本没有联系,最好的做法是让它们为内部的主要类命名,但不是必需的。但是,如果您要进行任何资源引用,这些是对文件而不是代码的引用,因此会破坏一个示例是

    在 app.XAML 中

    <Application x:Class="AppNamespace.App"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:local="clr-namespace:AppNamespace"
                 StartupUri="MainWindow.xaml" >
    </Application>
    

    这里 x:Class="AppNamespace.App" 是类引用,因此不受文件名影响,但 StartupUri="MainWindow.xaml" 是资源引用所以会受到文件名更改的影响

    关于你的其他问题

    我认为首先你需要回顾一下 WPF 的基础知识,它被优化为使用 MVVM 模式,原理相当简单,你将应用程序分成 3 层

    数据层或模型:该层处理对外部数据的访问,例如 Web 服务、数据库、保存文件等,这是该层唯一应该做的事情,它从不与前端对话 请注意,如果您收到来自外部数据源的有关更改的通知,它们会在此处处理。

    业务层或视图模型,该层处理模型和视图之间的所有通信,该层处理所有业务逻辑并通知前端它需要更新 请注意,这不一定是一对一的关系

    Gui 或 View 层,该层处理所有格式和用户交互 当用户更改数据时,视图将这些更改传递给视图模型,然后视图模型将决定何时或是否将更改传递给模型进行保存

    作为一个简单的例子

    //Model possibly generated by LinqToSQL, Entity Framework or simalar, in which case most of this will be done for you automatically
    public class Person
    {
        public string FirstName{get;set}
        public string SurnameName{get;set}
        public DateTime DateOfBirth{get;set}
        public static Person Load()
        {
            //get person from DB
        }
        public void Save()
        {
            //copy record to DB
        }
    }
    //Read only ViewModel converts model into the required format INotifyPropertyChanged used to inform View about changes to class as notified by the model
    public class PersonShort:INotifyPropertyChanged
    {
        private Person model;
        public string Name{get;} => model.FirstName + " " + model.FirstName;
        public int Age => (DateTime.Today - model.DateOfBirth);
    
        public void Save()
        {
            //copy record to DB
        }
    }
    //Editable ViewModel converts model into the required format and allows editing with INotifyPropertyChanged used to inform View about changes to class as notified by the model or as a result from changes in the view, note that because the Person is held separately in the VM undoing is possible
    public class PersonEdit:INotifyPropertyChanged
    {
        private Person model;
        public string FirstName{get;set}
        public string SurnameName{get;set}
        public DateTime DateOfBirth{get;set}
        public string ValidationMessage{get;set}
    
        public void Save()
        {
           if(validatedata)
           {
               model.FirstName = Firstname;
               model.Surname = Surname;
               model.DateOfBirth= DateOfBirth;
               model.Save();
           }
        }
        public void Cancel()
        {
               FirstName = model.Firstname;
               Surname = model.Surname;
               DateOfBirth= model.DateOfBirth;
        }
    }
    

    然后您将使用数据绑定将您的 Gui 连接到视图模型

    <Textbox Text={binding FirstName} />
    

    一旦你正确设置了这个,你遇到的问题就会变得简单得多

    您可以将搜索条件输入到您的视图中,然后 ViewModel 将对其进行格式化和正确验证(它是空的,当您期望字符串时它是一个 int,它是使用一个触发的还是 5,等等)然后将其传递给您的模型以在数据库上执行查询,如果使用 EF 或 LinqToSQL,则类似于

    //perform string search
    DbContext.Users.Any(u=>u.Username == SearchString);
    //perform ID search
    DbContext.Users.Find(UserID);
    //Add new users
    DbContext.Users.Add(new User(){//populate details});
    DbContext.Save();
    

    【讨论】:

    • 我确实有模型类,它们只是使用 LINQ 生成的(至少,只要它们在数据库中)。然而,这也很有帮助,所以谢谢。
    • WPF 与大多数 GUI 工具非常不同,因为它完全基于 GUI,它只是平面不能作为代码优先模型工作,这使它具有极大的灵活性和自适应能力来做任何事情,但是让你的头脑转起来真是太难了,所以我对你的挣扎和试图从你习惯的代码优先方向接近它并不感到惊讶。但这确实是错误的方法,您需要从 Gui 和模型的决斗方向来,然后创建视图模型作为它们之间的接口
    猜你喜欢
    • 2021-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-11
    • 2010-10-05
    • 2015-12-22
    • 1970-01-01
    相关资源
    最近更新 更多