简体   繁体   中英

DataBinding a ComboBox's SelectedValue in WinRT Prism/MVVM

I am having an issue with trying to bind a ComboBox in WinRT. I am using Prism/MVVM. I am able to bind the ItemsSource to an ObservableCollection no problem, and the ComboBox is being populated.

What I am having trouble with, is having it automatically select the appropriate value based on the current Invoice . Here is the relevant XAML:

<ComboBox Grid.Row="0" Grid.Column="1" Height="30" 
          ItemsSource="{Binding Path=Payees}"
          DisplayMemberPath="AccountName"
          SelectedValuePath="PayeeId"
          SelectedValue="{Binding CurrentInvoice.PayeeId, Mode=TwoWay}"
          Margin="5,0,10,0" />

Payees is my ObservableCollection and CurrentInvoice is a property on the ViewModel that points to the currently loaded Invoice item. The Invoice has a property called PayeeId , which as you may guess, is the Id of the Payee that this Invoice is associated to.

For some reason, no matter which Invoice I select, the ComboBox is blank when I navigate to my page. By blank, I just mean there is nothing selected, but it is populated with the Payees collection.

If I manually change the selection, and save my Invoice , the PayeeId isn't changed. I think that it probably has something to do with the binding on the SelectedValue , but so far I have been unable to figure this one out. Thanks in advance for any help!

Here are the properties for the Payees and CurrentInvoice :

private Invoice _currentInvoice;
public Invoice CurrentInvoice {
    get { return _currentInvoice; }
    set { SetProperty(ref _currentInvoice, value); } 
}

private ObservableCollection<Payee> _payees;
public ObservableCollection<Payee> Payees
{
    get { return _payees; }
    set { SetProperty(ref _payees, value); }
}

EDIT:

I have added a property on the ViewModel called SelectedPayee that is bound to the SelectedItem property of the ComboBox . Here is the updated definition:

<ComboBox Grid.Row="0" Grid.Column="1" Height="30" 
          ItemsSource="{Binding Path=Payees}"
          DisplayMemberPath="AccountName"
          SelectedValuePath="Id"
          SelectedItem="{Binding Path=SelectedPayee, Mode=TwoWay}"
          Margin="5,0,10,0" />

When I select a Payee and save, it saves with the new PayeeId , but when I load the page it still does not load with the SelectedPayee displayed in the ComboBox . However, all is well in the designer. To further test, I have added a TextBox that is bound to SelectedPayee.Id :

<TextBox Grid.Row="7" Grid.Column="1" Text="{Binding Path=SelectedPayee.Id}" />

That displayed the correct number at design time and runtime, and is updated appropriately whenever I change the selection in the ComboBox . The only thing that is not working correctly is the ComboBox is not correctly displaying the Payee AccountName when I navigate to the page. As I said, the design view is correctly displaying the dummy data that I have in my designer ViewModel . Is there something special about a ComboBox that I am perhaps doing something in the wrong order?

EDIT 2:

I also am getting the exact same results using

SelectedValue={Binding Path=SelectedPayee.Id, Mode=TwoWay}

The binding is displaying the correct Payee.Id in the TextBox depending on which Payee is selected in the ComboBox , but it just does not display the SelectedPayee when I first navigate to the page (but the TextBox will be populated with the correct Id .) This is really a head scratcher to me....

EDIT 3:

I got it all straightened out. The final issue I had going was I was setting the SelectedPayee before actually loading the ComboBox , so there was no property changes to trigger the SelectedValue of the ComboBox to change. Once I moved the call to LoadPayees() above the assignment to SelectedValue , everything works like a charm. See answer below.

For anyone who stumbles upon this question looking for a solution, what I ended up finding out was that I was setting the SelectedPayee before loading the ComboBox . I moved the call to LoadPayees() up above the SelectedPayee assignment, and now everything works as expected! Here is my OnNavigatedTo() method for anyone interested:

public override async void OnNavigatedTo(object navigationParameter, NavigationMode navigationMode,
    Dictionary<string, object> viewModelState)
{
    _headerViewModel.PageTitle = "Invoice Details";

    await LoadPayees();
    if (navigationParameter is Invoice)
    {
        _isEditing = true;
        CurrentInvoice = navigationParameter as Invoice;

        var payee = await _payeesRepository.LoadByIdAsync(CurrentInvoice.PayeeId);
        SelectedPayee = payee;

        await LoadPayments();
    }
    else
    {
        CurrentInvoice = new Invoice
        {
            CreationDate = DateTime.Now,
            InvoiceDate = DateTime.Now,
            Frequency = "M"
        };
    }
    /* await LoadPayees(); was originally down here... oops! */

    base.OnNavigatedTo(navigationParameter, navigationMode, viewModelState);
}

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