0

Here's my situation. I have a solution coded where I type a string into a textbox and upon clicking an Add button, it populates the Listbox.

Now, I want to:

a) Save that string to an XML file immediately. b) When the window opens, I want to display the data from that XML file in the listbox

Here's what I got so far:

Class

    public class Accounts : INotifyPropertyChanged
    {
        private string m_AccountName;

        public event PropertyChangedEventHandler PropertyChanged;

        public string AccountName
        {
            get { return m_AccountName; }
            set
            {
                m_AccountName = value;
                OnPropertyChanged("AccountName");
            }
        }

        protected void OnPropertyChanged(string name)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(name));
            }
        }
    }
}

Code Behind

 public partial class Account : Window
    {
        private ObservableCollection<Accounts> AccountList = new ObservableCollection<Accounts>();

        public Account()
        {
            InitializeComponent();        
            this.accountListBox.ItemsSource = AccountList;
        }

        private void addBtn_Click(object sender, RoutedEventArgs e)
        {
            AccountList.Add(new Accounts { AccountName = accountaddTextBox.Text });
        }

XAML

<ListBox DisplayMemberPath="AccountName" Height="164" HorizontalAlignment="Left" Margin="12" Name="accountListBox" VerticalAlignment="Top" Width="161" />

This code works for populating the listbox after you hit the Add button.

I've tried adding an instance of XMLTextReader to Window_Loaded and use an ArrayList as well to try to read the XML file and load it, but when I use ItemsSource it comes back with an error that I have to use ItemControl.ItemsSource...

Here's what I have tried, but it fails:

private void Window_Loaded(object sender, RoutedEventArgs e)
        {           
            XmlTextReader reader = new XmlTextReader("Accounts.xml");
            ArrayList ar = new ArrayList();

            //  Loop over the XML file
            while (reader.Read())
            {
                //  Here we check the type of the node, in this case we are looking for element
                if (reader.NodeType == XmlNodeType.Element)
                {
                    //  If the element is "accounts"
                    if (reader.Name == "Accounts")
                    {
                        ar.Add(reader.Value);

                        accountListBox.ItemsSource = ar;
                    }
                }
            }

            reader.Close();
        }
Woody
  • 1,159
  • 3
  • 15
  • 25

2 Answers2

1

Make a ViewModel as AccountListViewModel

public class AccountListViewModel : INotifyPropertyChanged
{
    private ObservableCollection<Accounts> accountList= 
                                           newObservableCollection<Accounts>();
    private string accountName;
    ICommand AddAccountCommand {get;set;}

    public event PropertyChangedEventHandler PropertyChanged;

    public AccountListViewModel()
    {
        ReadAllAccountsFromXml();
        AddAccountCommand=new  RelayCommand(AddAccountToListAndSave);
    }

    private void ReadAllAccountsFromXml()
    {           
        XmlTextReader reader = new XmlTextReader("Accounts.xml");


        //  Loop over the XML file
        while (reader.Read())
        {
            //  Here we check the type of the node, in this case we are looking for element
            if (reader.NodeType == XmlNodeType.Element)
            {
                //  If the element is "accounts"
                if (reader.Name == "Accounts")
                {
                    var account = new Accounts()
                    account.AccountName=reader.Value;
                    AccountList.Add(account)
                }
            }
        }

        reader.Close();
    }

    private void AddAccountToListAndSave(object obj)
    {
        var account = new Accounts();
        account.AccountName=AccountnName;
        AccountList.Add(account);
        SaveListToXml();
    }

    private void SaveListToXml()
    {
        //Write Xml Saving Code Here With Object as AccountList
    }
    public ObservableCollection<Accounts> AccountList
    {
        get { return accountList; }
        set
        {
            accountList = value;
            OnPropertyChanged("AccountList");
        }
    }
    public string AccountName
    {
        get { return accountnName; }
        set
        {
            accountnName = value;
            OnPropertyChanged("AccountName");
        }
    }

    protected void OnPropertyChanged(string name)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(name));
        }
    }
}

In your Xaml.cs

public partial class Account : Window
{
    private ObservableCollection<Accounts> AccountList = new ObservableCollection<Accounts>();

    public Account()
    {
        InitializeComponent();        
        this.DataContext= new AccountListViewModel();
    }

}

IN your Xaml

<ListBox Height="164" HorizontalAlignment="Left" Margin="12" Name="accountListBox" VerticalAlignment="Top" Width="161" ItemSource=AccountList>
<ListBox.ItemTemplate>
    <DataTemplate>
         <TextBlock Text={Binding Path=AccountName}/>
    </DataTemplate>
</ListBox.ItemTemplate>
</ListBox>

<TextBox Text={Binding Path=AccountName,UpdateSourceTrigger=PropertyChanged}></TextBox>

<Button Command={Binding Path=AddAccountCommand}/>

I believe this should do it....

Ankesh
  • 4,847
  • 4
  • 38
  • 76
  • I think this will work. But I'm getting that `AddAccountCommand` does not exist in the current context, which I don't understand because we've defined it in `ICommand`... – Woody Jan 14 '12 at 18:36
  • @Woody I edited the answer. You have to use RelayCommand or some kind of commanding to invoke the function on ViewModel from view... I believe you search for `RelayCommand` on google and youll find one for sure or u can use `MVVMLight` toolkit... thats all you need... – Ankesh Jan 14 '12 at 19:08
  • Almost there bro... this is what I get: Argument 1: cannot convert from 'method group' to 'System.Action' AccountListViewModel.cs – Woody Jan 14 '12 at 21:04
  • This is the offending line: `AddAccountCommand = new RelayCommand(AddAccountToListAndSave);` I'm using MvvmLight toolkit – Woody Jan 14 '12 at 21:10
  • @Woody That means you are just stuck at the usage of MVVMToolkit... I Don't Seem to know why its giving that error.....But i think you can resolve it.... – Ankesh Jan 15 '12 at 12:20
  • @Woody Try this `AddAccountCommand = new RelayCommand((Action)(AddAccountToListAndSave))` – Ankesh Jan 15 '12 at 12:22
  • 1
    @Woody i believe this link will help you http://stackoverflow.com/questions/5298910/mvvm-light-relaycommand-parameters – Ankesh Jan 16 '12 at 04:39
  • that fixed the problem, but I'm still not seeing anything lol... here's what my XML looks like... everything else is identical to your code: ` test123 1111 ` – Woody Jan 16 '12 at 16:37
  • @Woody your class structure is different... Accounts is a Collection no a single class as you made there.. – Ankesh Jan 16 '12 at 18:37
0

It sounds like your just having trouble binding an ArrayList to the ListBox.

You're code isn't ideal but it looks like it should work.

Try running the below code and see what it gives you. If it works you might try comparing that to the code you have in your project and seeing what the differences are.

ArrayList ar = new ArrayList();
ar.Add("hello");
ar.Add("world");
this.accountListBox.ItemsSource = ar;

If you still don't have any luck please post the exact text of the error so we know what we're trying to fix...

Greg Sansom
  • 20,442
  • 6
  • 58
  • 76
  • I was mistaken, I'm not getting an error, it's just not showing anything, and then my code to add text doesn't work anymore. It has something to do with ItemsSource... – Woody Jan 14 '12 at 05:22
  • It boils down to binding an ArrayList to a ListBox - all the other stuff in your question is (I think) irrelevant. Have you tried running the above code in a new solution by itself? – Greg Sansom Jan 14 '12 at 08:40