简体   繁体   English

WPF和C#:类和接口问题

[英]WPF and C#: Trouble with Classes and Interfaces

I'm working on a bank account program. 我正在开展银行账户计划。 I'm using a base class, an interface, and two derived classes in addition to my main window class. 除了主窗口类之外,我还在使用基类,接口和两个派生类。 I am making a WPF application, and so far I am able to populate a ListBox with an ArrayList of class objects in that app just fine. 我正在制作一个WPF应用程序,到目前为止,我能够在该应用程序中使用类对象的ArrayList填充ListBox就好了。 However, when I go to modify any of the objects in the ArrayList, I'm running into difficulty repopulating the ListBox correctly. 但是,当我去修改ArrayList中的任何对象时,我很难正确地重新填充ListBox。 Any help will be greatly appreciated! 任何帮助将不胜感激!

This is my MainWindow code: 这是我的MainWindow代码:

 public partial class MainWindow : Window
 {
    ArrayList bankAccountList = new ArrayList();

    BankAccount savingsAccount = new SavingsAccount("New", "Account", "newaccount");
    BankAccount checkingAccount = new CheckingAccount("New", "Account", "newaccount");
    IAccount iAccount;
    string typeOfAccount = "";

    public MainWindow()
    {
        InitializeComponent();
    }

    //When the user pushes the "Add A Saving Account" button, a new savings account is added to the ArrayList and displayed in the app.
    private void btnAddAccount_Click(object sender, RoutedEventArgs e)
    {
        iAccount = (IAccount)savingsAccount;

        savingsAccount.Deposit(0.00m);

        bankAccountList.Add(savingsAccount);
        lbxExistingAccounts.Items.Add(iAccount.AccountInformation());
        typeOfAccount = "savings";
    }

    //When the user pushes the "Add A Checking Account" button, a new checking account is added to the ArrayList and displayed in the app.
    private void btnAddCheckingAccount_Click(object sender, RoutedEventArgs e)
    {
        iAccount = (IAccount)checkingAccount;

        checkingAccount.Deposit(0.00m);

        bankAccountList.Add(checkingAccount);
        lbxExistingAccounts.Items.Add(iAccount.AccountInformation());
        typeOfAccount = "checking";
    }

    //When the user pushes the "Delete Account" button, the account is removed, and this change is shown in the app.
    private void btnDeleteAccount_Click(object sender, RoutedEventArgs e)
    {
        lbxExistingAccounts.Items.RemoveAt(lbxExistingAccounts.Items.IndexOf(lbxExistingAccounts.SelectedItem));
    }

    //The user can push the "Submit Changes" button to submit his or her changes to the number and name of the account.
    private void btnSubmitChanges_Click(object sender, RoutedEventArgs e)
    {
        try
        {

            for (int index = 0; index < bankAccountList.Count; index++)
            {
                if (index == lbxExistingAccounts.SelectedIndex)
                {
                    if (typeOfAccount == "savings")
                    {
                        savingsAccount.AccountNumber = tbxAccountNumber.Text;
                        savingsAccount.AccountOwnerFirstName = tbxFirstName.Text;
                        savingsAccount.AccountOwnerLastName = tbxLastName.Text;
                    }

                    else if (typeOfAccount == "checking")
                    {
                        checkingAccount.AccountNumber = tbxAccountNumber.Text;
                        checkingAccount.AccountOwnerFirstName = tbxFirstName.Text;
                        checkingAccount.AccountOwnerLastName = tbxLastName.Text;
                    }
                }
            }
            lbxExistingAccounts.Items.Clear();
            foreach (object accountObject in bankAccountList)
            {
                lbxExistingAccounts.Items.Add(accountObject);
            }
        }
        catch (FormatException)
        {
            MessageBox.Show("You may enter changes as letters, numbers, or both.");
        }

    }

This is my Interface code: 这是我的接口代码:

interface IAccount
{
    void SetAccountBalance(decimal accountBalance);
    string AccountInformation();
}

This is my base class code: 这是我的基类代码:

    abstract class BankAccount
{
    public string AccountNumber { get; set; }
    public string AccountOwnerFirstName { get; set; }
    public string AccountOwnerLastName { get; set; }
    public decimal AccountBalance { get; set; }
    public decimal AnnualInteresetRate { get; set; }
    public string TypeOfAccount { get; set; }

    public BankAccount(string accountOwnerFirstName, string accountOwnerLastName, string accountNumber)
    {
        AccountOwnerFirstName = accountOwnerFirstName;
        AccountOwnerLastName = accountOwnerLastName;
        AccountNumber = accountNumber;
    }

    public abstract void Deposit(decimal amount);

    public abstract void Withdraw(decimal amount);

    public decimal CalculateInterest()
    {
        return (this.AccountBalance * this.AnnualInteresetRate) / 100;
    }
} 

This is one of my derived classes. 这是我的派生类之一。 I made both pretty much the same. 我两个都差不多。

    class SavingsAccount : BankAccount, IAccount
{
    public SavingsAccount(string accountOwnerFirstName, string accountOwnerLastName, string accountNumber)
        : base(accountOwnerFirstName, accountOwnerLastName, accountNumber)
    {
        AnnualInteresetRate = 0.95m;
    }

    public override void Deposit(decimal amount)
    {
        AccountBalance = AccountBalance + amount;
    }

    public override void Withdraw(decimal amount)
    {
        AccountBalance = AccountBalance - amount;
    }

    public void SetAccountBalance(decimal accountBalance)
    {
        AccountBalance = accountBalance;
    }

    public string AccountInformation()
    {
        return "Savings Account \n  " + AccountOwnerFirstName + " " + AccountOwnerLastName + ", Account#: " + AccountNumber + ", Balance: $" + AccountBalance;
    }
}

It looks like you are just starting out, which is good, because you are going to want to rework some things. 看起来你刚刚开始,这很好,因为你想要重做一些事情。

  1. You don't need to cast your derived objects to their base types. 您不需要将派生对象转换为其基类型。 This type of casting is called "upcasting" and automatically works without any casting whatsoever. 这种类型的铸造被称为“向上铸造”并且无需任何铸造即可自动工作。

  2. The code you posted is highly "WinForms-ish" and this is not a good approach in WPF. 您发布的代码高度“WinForms-ish”,这在WPF中不是一个好方法。 Start with making your account list an ObservableCollection and binding your ListBox's ItemsSource to it. 首先使您的帐户列表成为ObservableCollection并将ListBox的ItemsSource绑定到它。

The property would look like: 该属性看起来像:

public ObservableCollection<BankAccount> Accounts {get; set;}

Which should actually use INotifyPropertyChanged omitted for brevity, and the binding: 实际上应该省略INotifyPropertyChanged以简化和绑定:

<ListBox "ItemsSource={Binding Accounts}"/>

Of course, that should go in a view model class, but you could start with your code-behind by setting: 当然,这应该放在视图模型类中,但您可以通过设置以下代码开始:

DataContext = this;

Once that is working all your text boxes should be bound to properties of the data objects or of the view itself. 一旦工作,所有文本框都应绑定到数据对象或视图本身的属性。

Here is a great tutorial on using MVVM with WPF ( MSDN ). 这是一个使用MVVM和WPF( MSDN )的好教程。 Trust me, using this design pattern will make your work with WPF immensely easier, more extensible, and you will find that WPF was basically designed to use it. 相信我,使用这种设计模式将使您使用WPF的工作变得更加容易,更具可扩展性,并且您会发现WPF基本上是为使用它而设计的。 Using a WinForms approach is just going to cause you pain. 使用WinForms方法只会让你感到痛苦。

Please let me know if I can assist further or clarify anything! 如果我能进一步协助或澄清任何事情,请告诉我!

I would recommend using ObservableCollection for your collection, so that any changes made to the items would be reflected visually without any additional work. 我建议您为集合使用ObservableCollection ,这样对项目所做的任何更改都将在视觉上反映出来,而无需任何额外的工作。 It wouldn't require any significant changes. 它不需要任何重大改变。 All you would do is switch your ArrayList for an ObservableCollection . 您要做的就是切换ArrayList以获取ObservableCollection

http://msdn.microsoft.com/en-us/library/ms668604(v=vs.110).aspx http://msdn.microsoft.com/en-us/library/ms668604(v=vs.110).aspx

I would also highly recommend implementation of INotiftyPropertyChanged interfrace for your objects, so that when account information is changed, appropriate subscribers are notified. 我还强烈建议为您的对象实现INotiftyPropertyChanged ,以便在更改帐户信息时通知相应的订阅者。

http://msdn.microsoft.com/en-us/library/vstudio/system.componentmodel.inotifypropertychanged http://msdn.microsoft.com/en-us/library/vstudio/system.componentmodel.inotifypropertychanged

I've been using both of those extensively with my WPF applications. 我在WPF应用程序中广泛使用这两种方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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