简体   繁体   中英

How to bind to a list that nested deep in the DataContext object in WPF

I need to bind to a list of objects that is hidden deep inside the DataContext object and it doesn't seem to be working for me. Here is my DataContext object:

public class UserDataContext
{
    public ObservableCollection<UserViewModel> Users { get; set; }
    public UsersSettingsViewModel UserSettings { get; set; }
}


public class UsersSettingsViewModel
{
    public int Id { get; set; }
    public ObservableCollection<Subscriptions> Subscriptions { get; set; }
} 

I have a list of users, bound to Users property and when a user is selected, I want to display settings defined for the user. Settings are kept in UsersSettingsViewModel class and at the moment it is just a list of user's subscriptions. I set DataContext to an instance of UserDataContext at the beginning. Then I dynamically load UserSettingsViewModel object for the selected user in the SelectionChanged event handler:

private void OnUserSelectionChanged(object sender, SelectionChangedEventArgs e)
{
   if (lwUsers.SelectedItem == null)
       return;

   var selectedUser = (UserViewModel)lwUsers.SelectedItem;
   var settings = _usersSettingsDal.Load(selectedUser.Login) ?? _usersSettingsDal.Create(selectedUser.Login);
   UserDataContext.UserSettings = _usersSettingsDal.ToViewModel(settings);
}

Although I don't have any problems in binding to Users property from XAML, for some reason I can't get the Subscriptions property to be displayed at all. It just doesn't do anything:

<GroupBox Header="Subscriptions" Name="gbSubscriptions">
                            <StackPanel Margin="10,10,10,10">
                                <ListView ItemsSource="{Binding UserDataContext.Subscriptions}">
                                    <ListBox.ItemTemplate>
                                        <DataTemplate>
                                            <StackPanel>
                                                <TextBlock Text="{Binding Path=Name, diag:PresentationTraceSources.TraceLevel=High}"   />
                                                <CheckBox IsChecked="{Binding Path=Enabled, diag:PresentationTraceSources.TraceLevel=High}" />
                                            </StackPanel>
                                        </DataTemplate>
                                    </ListBox.ItemTemplate>
                                </ListView>
                            </StackPanel>
                        </GroupBox>

Do I need to refresh DataContext somehow? Or maybe UserDataContext.Subscriptions is not a legitimate path for Binding? Any thoughts?

Referencing nested properties using Binding Path s is very similar to referencing the same properties in code. Take these examples:

int age = SomeParent.SomeChild.Age;  

"{Binding Path=SomeParent.SomeChild.Age}"


SomeObject object = SomeCollection[0].SomeChild.SomeObject;

"{Binding Path=SomeCollection[0].SomeChild.SomeObject}"


double value = SomeClass.SomeObjectProperty.SomeCollection[0].SomeProperty;

"{Binding Path=SomeClass.SomeObjectProperty.SomeCollection[0].SomeProperty}"

For a more substantial list of Binding Path syntax, please view the Binding.Path Property page on MSDN.

您能否尝试使用此绑定而不是您的绑定:

<ListView ItemsSource="{Binding Path=UserDataContext.UserSettings.Subscriptions}">

Basically when you do:

UserDataContext.UserSettings = _usersSettingsDal.ToViewModel(settings);

you should raise a propertychange event as @toadflakz says, something like:

RaiseProperyChanged(()=>UserDataContext.UserSettings);

And the binding is also incorrect. The correct is as @Greenonion says:

<ListView ItemsSource="{Binding Path=UserDataContext.UserSettings.Subscriptions}">

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