1

I have a WPF project which uses, as best I can, the MVVM pattern. I'm using Visual Studio 2010, and the language behind is C#.

So I have a treeview. The treeview looks like this:

<TreeView Grid.Column="0" Width="Auto" Background="Aquamarine" ItemsSource="{Binding Scenes}" SelectedItemChanged="TreeView_SelectedItemChanged">
        <TreeView.DataContext>
            <viewModels:ScenesViewModel />
        </TreeView.DataContext>
        <TreeView.ItemTemplate>
            <HierarchicalDataTemplate ItemsSource="{Binding Characters}">
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="{Binding SceneName}"></TextBlock>

                        <Image Source="{StaticResource ImgWorld}" Margin="0,0,5,0" Width="32" Height="32"/>

                </StackPanel>
                <HierarchicalDataTemplate.ItemTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal">

                            <TextBlock Text="{Binding FirstName}"></TextBlock>
                            <Border BorderThickness="1" Background="RoyalBlue">
                                <Image Source="{Binding ImgIcon}" Margin="2"/>
                            </Border>
                        </StackPanel>
                    </DataTemplate>
                </HierarchicalDataTemplate.ItemTemplate>
            </HierarchicalDataTemplate>
        </TreeView.ItemTemplate>
    </TreeView>

The point of contention is the Image, the source of which is bound to something called 'ImgIcon'. This is a property of a view model called 'CharacterViewModel'. For some reason I am getting nothing displayed where the image should be.

The most obvious issue might be regarding the data context or whether the MVVM side of things is working. I am fairly sure it is, as there is a TextBlock next to the Image which is also bound to a property called 'FirstName'. This binding works fine.

The two properties are, of course, in the view model, and can be seen here:

public String FirstName
    {
        get { return Character.FirstName; }
        set
        {
            if (Character.FirstName != value)
            {
                Character.FirstName = value;
                RaisePropertyChanged("FirstName");
            }
        }
    }

private BitmapImage _imgIcon = null;
    public BitmapImage ImgIcon 
    { 
        get { return _imgIcon; }
        set 
        {
            _imgIcon = value;
            RaisePropertyChanged("ImgIcon");
        }
    } 

They are slightly different in that the latter does not wrap around a property in the Character class.

So the next possible fault would be the loading of the image. This is accomplished by this method (which at the moment just has a test path for a known working file):

public bool LoadIcon()
    {
        if (ImgIcon == null)
        {
            Uri outUri;

            if (Uri.TryCreate(@"D:\Pictures\Icons\HCAria01.png", UriKind.Absolute, out outUri) )
            {
            }


            ImgIcon = new BitmapImage(outUri);
            return true;
        }
        else
            return false;
    }

I put a break point in at 'ImgIcon = new BitmapImage(outUri)' and you can see the relevant information here: picture. It seems from this picture that the image has loaded successfully.

I'm sure I'm missing something obvious, but I'm damned if I can say what it is. From my limited experience with WPF and XAML, it seems to be working okay, except for the lack of an image.

Well, if you can offer any help that would be much appreciated.

Edit: a couple of clarifications. The DataContext for the Treeview is called ScenesViewModel. This holds a list of SceneViewModel, and that list is called 'Scenes'. Each SceneViewModel containst a list of CharacterViewModel, and that is called 'Characters'. These two images show the relevant part of those classes, so hopefully the hierarchy can be understood. For each CharacterViewModel, there should be an ImgIcon.

1
  • 1
    From a quick glance since the Image is loading in code, I would double check your context is actually your object with the ImgIcon property and not your Character object which has the exact same property name for FirstName. Commented Mar 8, 2017 at 20:34

2 Answers 2

1

Make sure that you bind to the view model (ScenesViewModel) property if the ImgIcon property is defined in this class:

<Image Source="{Binding DataContext.ImgIcon, RelativeSource={RelativeSource AncestorType=TreeView}}" Margin="2"/>

The DataContext of the StackPanel in the ItemTemplate is an item in the ItemsSource and not the view model.

Edit: You should define one template for SceneViewModel objects and another one for CharacterViewModel objects. You could put the implicit templates in the section of the TreeView:

<TreeView Grid.Column="0" Width="Auto" Background="Aquamarine" ItemsSource="{Binding Scenes}" 
                  SelectedItemChanged="TreeView_SelectedItemChanged">
    <TreeView.DataContext>
        <viewModels:ScenesViewModel />
    </TreeView.DataContext>
    <TreeView.Resources>
        <HierarchicalDataTemplate DataType="{x:Type local:SceneViewModel}" ItemsSource="{Binding Characters}">
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="{Binding SceneName}"></TextBlock>
                <Image Source="{StaticResource ImgWorld}" Margin="0,0,5,0" Width="32" Height="32"/>
            </StackPanel>
        </HierarchicalDataTemplate>
        <DataTemplate DataType="{x:Type local:CharacterViewModel}">
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="{Binding FirstName}"></TextBlock>
                <Border BorderThickness="1" Background="RoyalBlue">
                    <Image Source="{Binding ImgIcon}" Margin="2"/>
                </Border>
            </StackPanel>
        </DataTemplate>
    </TreeView.Resources>
</TreeView>
Sign up to request clarification or add additional context in comments.

6 Comments

Just to clarify, the DataContext is called 'ScenesViewModel'. This contains a list of SceneViewModel called 'Scenes'. Each SceneViewModel contains a list of CharacterViewModel called 'Characters'. It is in CharacterViewModel that ImgIcon is.
In which class is the ImgIcon defined?
CharacterViewModel. I edited my original question to try to clear up the hierarchy.
What is "ImgWorld"? Do you see this Image resource?
Yes, I see that fine. That, however, is a resource in the user control, unlike the one I'm having issues with. If I replace my ImgIcon with the static resource ImgWorld, it works okay and I can see it clearly where I would expect to.
|
0

This answer is for those looking to see what happened - maybe you have the same issue.

My problem was actually elsewhere in my code. When I loaded a Scene (data model) from my database to populate the SceneViewModel's data, I created one instance which I used to load the image, and then added a new instance to the list. So there were two instances, one which was created, used to load the images and then not used, and another which was used (but which didn't have the images loaded). Basically it was a simple mistake and not related to the code seen here - that all worked fine (since now that I corrected the error, things work as they should, images and all).

Thanks to all those who took the time to answer.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.