简体   繁体   中英

WPF handling click event with a database

I'm trying to get started with WPF at the moment. I have some experience with android and java, but i've never used C#. I've set up a database, I established a connection with the database and used LINQ to create all the getters and setters for the database (Visual Studio), called databaselink.dbml.

I've created a simple register window (I know, passwords are not supposed to be in plain text nor should they be stored in variables, but this is simply to simplify the application, I have no intention of actually using this).

<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>

So I've set a click for my register button. My code, at the moment, looks like this:

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.
        }
    }

    }
}

First of all, I renamed my window to 'Registerwindow.xaml' and Registerwindow.xaml.cs. Nothing in my code changed, is this normal? In android, the code gets refactored because the names have to be the same, is this not the case in WPF?

My link class:

#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();
    }

Could anyone help me on my way with this please? If I have an example I can continue using it to do all the other database related stuff. Sorry if this seems silly.

Oh, my question in case it wasn't clear: how do I now check if the user exists in my database, and add it if it doesn't.

First of all, I renamed my window to 'Registerwindow.xaml' and Registerwindow.xaml.cs. Nothing in my code changed, is this normal? In android, the code gets refactored because the names have to be the same, is this not the case in WPF?

File names have nothing to do with the compiled end results there is no link between the file name and the content at all, its best practice to have them named for the primary class inside but not required. however if you are making any resource references these are to the file not the code so will break an example is

in the 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>

here x:Class="AppNamespace.App" is a class reference so is unaffected by the file name but StartupUri="MainWindow.xaml" is a resource reference so would be affected by a change in filename

in relation to your other question

i think firstly you need to review the basics of WPF, it is optimised to work with the MVVM pattern, the principle is fairly simple, you split your application into 3 layers

the Data layer or Model: this layer handles access to external data such as web services, databases, save files, etc, this is the only thing this layer should do, it never talks to the front end Note if you have notification from external data sources about changes they are handled here.

The Business layer or View Model, this layer handles all communcation between the Model and the View, this layers handles all business logic and informs the front end that it needs to update Note this doesn't have to be a 1 to 1 relationship

The Gui or View layer, this layer handles all formatting and user interaction when a users changes data the View passed those changes to the View Model, the view model will then decide when or if changes are passed to the model for saving

as a simple example

//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;
    }
}

you would then use databinding to connect your Gui to the viewmodel

<Textbox Text={binding FirstName} />

once you have this set up correctly the problem you have becomes much simpler

you would feed your search criteria into your view, this will then be formatted and validated correctly (is it empty, is it a int when you are expecting strings, is it using one fired or 5, etc) by the ViewModel which will then pass it to your Model to execute the Query on the database, which if using EF or LinqToSQL would be something like

//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();

Your question as-is doesn't appear to be a WPF issue, it's about your data access layer. You will want to do more research into LinqToSql, but to get you started.

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.");
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM