Question

Can you tell me why this code isn't working?

I have a viewmodel with an observablecollection of searchresults which has an observablecollection of resultproperties. I cannot seem to display the nested collection of result properties like I want.

Here are the objects (abstracted for readability):

class ViewModel
{
    public ObservableCollection<SearchResults<TDomain>> SearchResults { get; set; }
}

class SearchResults<TDomain>
{
    public TDomain Result { get; set; }
    public ObservableCollection<ResultProperty> ResultProperties { get; set; }
}

class ResultProperty
{
    public string PropertyValue { get; set; }
}

Here is the xaml I cannot get to work. The DataContext is set to the ViewModel:

<StackPanel>
    <ItemsControl ItemsSource={Binding SearchResults}>
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <StackPanel>
                    <TextBlock Text={Binding Result.Id}/>
                    <StackPanel Orientation="Horizontal">
                        <ItemsControl ItemsSource={Binding ResultProperties}>
                            <ItemsControl.ItemTemplate>
                                <DataTemplate>
                                    <TextBlock Text="{Binding PropertyValue}" />
                                </DataTemplate>
                            </ItemsControl.ItemTemplate>
                        </ItemsControl>
                    </StackPanel>
                </StackPanel>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
    <TextBlock Text="PLACEHOLDER /////"/>
</StackPanel>

The outcome I am looking for is something like this:

[Stack panel to keep things orderly]
1
property1property2property3...
2
property1property2property3...
3
property1property2property3...
PLACEHOLDER /////

The results I am getting are these

[Stack panel to keep things orderly]
1

2

3

PLACEHOLDER /////

In otherwords, the binding isn't picking up the string. I have verified that the collections are populating like expected. But I can't get the xaml to work.

**ADDITION INFORMATION

Ok, so I tried some of the solutions, but they aren't working so I am going to add more details because maybe I am missing something about how the collections are getting updated.

The viewmodel has a button on it called "Search" which uses an ICommand that calls a the view model's TrySearch method which is below:

public void TrySearch()
{
    var results = _model.GetAll();
    foreach(var result in results)
        this.SearchResults.Add(new SearchResults<TDomain>(result));
}

Could there be a reason this doesn't work because of the way the collection is updated? SearchResults is a dependency property (I know I know, it should be INPC, but its not, its dependency), but the other collections are not. Could this be a problem?

Was it helpful?

Solution 3

The answer is that my SearchResults class was not hooked up properly. I made it a dependency object with dependency properties and it works fine. I am assuming that would translate similarly if it was INotifyPropertyChanged. Thank you for the responses.

OTHER TIPS

I would create the data templates as resources and refer to them elsewhere in the XAML. For example:

<Window ....>

    <Window.Resources>
        <DataTemplate x:Key="SearchResultTemplate" TargetType="SearchResults">
            <TextBlock Text={Binding PropertyValue}"
        </DataTemplate>

        <DataTemplate x:Key="ViewModelTemplate" TartgetType="ViewModel">
            <StackPanel>
                <TextBlock Text={Binding Result.Id}/>
                <StackPanel Orientation="Horizontal">
                    <ItemsControl ItemsSource={Binding ResultProperties} ItemTemplate="{StaticResource SearchResultTemplate}" />
                </StackPanel>
            </StackPanel
        </DataTemplate>

    </Window.Resources>

    <StackPanel>
        <ItemsControl ItemsSource={Binding SearchResults} ItemTemplate="{StaticResource ViewModelTemplate}" />
</Window>

I'm not sure, but I think that the bindings you're using are telling the XAML parser to look for properties of the ViewModel class called ResultProperties and PropertyValue. The XAML parser doesn't see that they're properties of the object bound to that instance of the collection. Splitting it up like this should make it plain that the properties belong to the instance that the template is being applied to.

Your code is somehow correct but according to what you want it has a flow. The StackPanel has to be the ItemsPanel. Change it like this:

    <StackPanel>
        <ItemsControl ItemsSource="{Binding SearchResults}">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <StackPanel>
                        <TextBlock Text="{Binding Result.Id}"/>
                        <ItemsControl ItemsSource="{Binding ResultProperties}">
                            <ItemsControl.ItemsPanel>
                                <ItemsPanelTemplate>
                                    <StackPanel Orientation="Horizontal" IsItemsHost="True"/>
                                </ItemsPanelTemplate>
                            </ItemsControl.ItemsPanel>
                            <ItemsControl.ItemTemplate>
                                <DataTemplate>
                                    <TextBlock Text="{Binding PropertyValue}" />
                                </DataTemplate>
                            </ItemsControl.ItemTemplate>
                        </ItemsControl>
                    </StackPanel>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
        <TextBlock Text="PLACEHOLDER /////"/>
    </StackPanel>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top