mauryat
mauryat

Reputation: 1646

Establishing Data-Binding in WPF

I'm finding it challenging to get data-binding working for my sample WPF application in the MVVM style.

Question:

What's missing in the following sample?


Details:

Basic Structure:

Model: Customer (doesn't matter actually)

ViewModel: AllCustomersViewModel

View: WizardWindowView

Structural elements:

Exposed by VM: AllCustomers (of type ObservableCollection)

Displayed on View: ListView

Want Binding: ListView <-> AllCustomers


WizardWindowView.xaml:

<Window 
    ...
    ...
    <Window.Resources>
        <CollectionViewSource x:Key="CustomerGroups" Source="{Binding Path=AllCustomers}"/>
    </Window.Resources>
    
    <Grid>
            ...
            ...
            <aw:WizardPage Header="Step 1">
                <ListView
                   ItemsSource="{Binding Source={StaticResource CustomerGroups}}"/>
            </aw:WizardPage>
            ...
            ...
    </Grid>
</Window>

I've already spent more than 10 hours trying to understand how data-binding is accomplished and feel it's time to ask for help!


EDIT

Model info:

Data: customers.xml

Model: Customer.cs

Data Access: CustomerRepository.cs

AllCustomersViewModel:

readonly CustomerRepository _customerRepository;
public AllCustomersViewModel(CustomerRepository customerRespository) {...}

EDIT 2

Sequence of calls:

App.xaml.cs.OnStartup() {.. new MainWindowViewModel("Data/customers.xml")..};

public MainWindowViewModel(string customerDataFile)
{
    _customerRepository = new CustomerRepository(customerDataFile);
    new AllCustomersViewModel(_customerRepository);
}

EDIT 3

DataContext:

In App.xaml.cs:

    MainWindow window = new MainWindow();
    string path = "Data/customers.xml";
    var viewModel = new MainWindowViewModel(path);
    window.DataContext = viewModel;

In MainWindow.xaml.cs (the codebehind):

private void ShowWizardWindow(object sender, RoutedEventArgs e)
{
    Views.WizardWindowView wizardWindow = new Views.WizardWindowView();
    wizardWindow.DataContext = this.DataContext;
    wizardWindow.Show();
}

Upvotes: 0

Views: 321

Answers (2)

mauryat
mauryat

Reputation: 1646

After assistance from several people here, from my colleague and finally from some reading, I managed to establish data-binding! Actually, a simplified one compared to what I was originally hoping.

Sorry, my answer might not be the most organized, but I'm sure it'll be understandable.


Accomplished

Displaying names of customers.


Here's how

I have a WizardWindowView (similar to a WPF Window) on which I wanted to display the names of customers. WizardPage is a window (again, similar to a WPF Window) among several windows in the wizard. I also have the data-context set as in the question's edit section.

Where are the names of the customers originally coming from?
I have a data source which is an xml file. I also have a AllCustomersViewModel.cs class that gives an abstraction for the data in the xml file. If you want to know how the abstraction is done, you might have to do some reading on WPF! The abstraction is a collection of CustomerViewModel objects.

Now, what are these CustomerViewModel objects?
If AllCustomersViewModel abstracts the collection of customer data in the original xml file, CustomerViewModel abstracts each customer in the collection.

What is the abstraction like or what is its type?
CustomerViewModel exposes (this is .net jargon) a property called FirstName of type string. AllCustomersViewModel exposes a property called AllCustomers of type ObservableCollection<CustomerViewModel>.

Now that I have the data to be displayed, I'm switching my focus to the View (xaml):
I'm trying to display the first names of the customers on my WizardWindowView.

Since I have to display a list and not just one or two elements in the list, I need a xaml control to display a list (ListView).

What should the source for ListView be?

<ListView ItemsSource="{Binding Path=AllCustomers}">

To display each item in the list, I do the following:

            <ListView.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Path=FirstName}"></TextBlock>
                </DataTemplate>
            </ListView.ItemTemplate>

Summary:

<aw:WizardPage Header="Step 3: Edit/Check Engine (Faulty Customers)">
    <ListView ItemsSource="{Binding Path=AllCustomers}">
        <ListView.ItemTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding Path=FirstName}"></TextBlock>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</aw:WizardPage>

Upvotes: 1

Steven Licht
Steven Licht

Reputation: 770

In the Code-behind for the view you need to set the DataContext = ViewModel public WizardWindowView() { ... DataContext = new MainWindowViewModel(); ... } or in OnStartup() { App.MainWindow.DataContext = new MainWindowViewModel(); } Setting Window's DataContext is your missing piece.

Upvotes: 1

Related Questions