none
Binding an image to a listview in C# is just displaying the path, not the image

    Question

  • What is wrong with this picture?

    This is a screen capture of a detail of a listview. See where it says AlethopterisYoung.bmp? That's supposed to be a picture of a prehistoric plant. Instead, all I'm seeing is the path (for brevity I've truncated the whole string).

    Here's the XAML:

    <Window x:Class="DinosaurIsland.PlantDisplay"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:DinosaurIsland"
        Title="Vegetation" Height="308" Width="1212" WindowStyle="SingleBorderWindow"
        DataContext="{Binding RelativeSource={RelativeSource Self}}" Loaded="Window_Loaded">
        <Window.Resources>
            <DataTemplate x:Key="YoungPicCell">
                <StackPanel Orientation="Horizontal">
                    <Image Height="200" Width="200" Name="YoungPicture"  Stretch="None"  Source="{Binding YoungPicBmp}"    />
                </StackPanel>
            </DataTemplate>
            <DataTemplate x:Key="MediumPicCell">
                <StackPanel Orientation="Horizontal">
                    <Image Height="200" Width="200" Name="MediumPicture"  Stretch="None" Source="{Binding MediumPicBmp}" />
                </StackPanel>
            </DataTemplate>
            <DataTemplate x:Key="AdultPicCell">
                <StackPanel Orientation="Horizontal">
                    <Image Height="200" Width="200" Name="AdultPicture" Stretch="None" Source="{Binding Path=AdultPicBmp}" />
                </StackPanel>
            </DataTemplate>

            <DataTemplate x:Key="TerrainCell">
                <StackPanel Orientation="Vertical">
                    <CheckBox Content="Salt Water"  Name="SaltWaterCheckbox" IsThreeState="False" IsChecked="{Binding SaltWater}" />
                    <CheckBox Content="Fresh Water"  Name="FreshWaterCheckbox" IsThreeState="False" IsChecked="{Binding FreshWater}" />
                    <CheckBox Content="Grassland / Plains"  Name="GrasslandsCheckbox" IsThreeState="False"  IsChecked="{Binding Grasslands}" />
                    <CheckBox Content="Swamp"  Name="SwampCheckbox" IsThreeState="False" IsChecked="{Binding Swamp}" />
                    <CheckBox Content="Tropical Forest"  Name="TropicalForestCheckbox" IsThreeState="False"  IsChecked="{Binding TropicalForest}" />
                    <CheckBox Content="Forest"  Name="ForestCheckbox" IsThreeState="False" IsChecked="{Binding Forest}" />
                    <CheckBox Content="Forest Edge"  Name="ForestEdgeCheckbox" IsThreeState="False"  IsChecked="{Binding ForestEdge}" />
                    <CheckBox Content="Sand"  Name="SandCheckbox" IsThreeState="False" IsChecked="{Binding Sand}" />
                    <CheckBox Content="Coastal"  Name="CoastalCheckbox" IsThreeState="False" IsChecked="{Binding Coastal}" />
                    <CheckBox Content="River Border"  Name="RiverBorderCheckbox" IsThreeState="False" IsChecked="{Binding RiverBorder}" />
                    <CheckBox Content="LakeBorder"  Name="LakeBorderCheckbox" IsThreeState="False"  IsChecked="{Binding LakeBorder}" />
                    <CheckBox Content="Floodplain"  Name="FloodplainCheckbox" IsThreeState="False"  IsChecked="{Binding Floodplain}" />
                </StackPanel>
            </DataTemplate>

            <DataTemplate x:Key="PlacePlantsCell">
                <StackPanel Orientation="Vertical">
                    <Label Margin="10"  Content="Random" HorizontalAlignment="Center" ></Label>
                    <Slider Margin="10"  Width="190" Value="50" Orientation="Horizontal" HorizontalAlignment="Center" IsSnapToTickEnabled="True" Maximum="100" TickPlacement="BottomRight"  TickFrequency="5"> </Slider>
                    <Button Margin="10"  Content="Randomly Seed Plants" HorizontalAlignment="Center"  Height="23" Name="SeedButton" ></Button>
                </StackPanel>
            </DataTemplate>
        </Window.Resources>

        <DockPanel>
            <Grid>
                <ListView ItemsSource="{Binding Path=lsvData, Mode=TwoWay}" Name="listView1">
                    <ListView.View>
                        <GridView>
                            <GridViewColumn Width="152" Header="Name" DisplayMemberBinding="{Binding Path=Name}"  />
                            <GridViewColumn Width="202" Header="Picture of Young Plant" DisplayMemberBinding="{Binding Path=YoungPic}" CellTemplate="{StaticResource YoungPicCell}" />
                            <GridViewColumn Width="202" Header="Picture of Medium Plant"  DisplayMemberBinding="{Binding Path=MediumPic}" CellTemplate="{StaticResource MediumPicCell}" />
                            <GridViewColumn Width="202" Header="Picture of Adult Plant"  DisplayMemberBinding="{Binding Path=AdultPic}" CellTemplate="{StaticResource AdultPicCell}" />
                            <GridViewColumn Width="202" Header="Terrain / Environments" CellTemplate="{StaticResource TerrainCell}" />
                            <GridViewColumn Width="202" Header="Place Plants" CellTemplate="{StaticResource PlacePlantsCell}" />
                        </GridView>
                    </ListView.View>
                </ListView>
                <Button Content="New Plant"  DockPanel.Dock="Bottom"  Height="23" HorizontalAlignment="Left" Margin="160,240,0,0" Name="NewPlant" VerticalAlignment="Top" Width="75" Click="NewPlant_Click" />
                <Button Content="Save" DockPanel.Dock="Bottom"   Height="23" HorizontalAlignment="Center" Margin="1099,240,15,0" Name="SavePlant" VerticalAlignment="Top" Width="75" Click="SavePlant_Click"/>
                <Button Content="Load" DockPanel.Dock="Bottom" Height="23" HorizontalAlignment="Left" Margin="26,240,0,0" Name="LoadPlants" VerticalAlignment="Top"  Click="LoadPlants_Click" Width="75" />
            </Grid>
        </DockPanel>
    </Window>

    And here's the C# code that loads the XML file with the data and (supposedly) binds the image:

           public WindowViewModel _wvm;

            public PlantDisplay()
            {
                InitializeComponent();
                _wvm = new WindowViewModel();
                this.DataContext = _wvm;
            }

            public class LVData
            {
                public string Name { get; set; }
                public string YoungPic { get; set; }
                public BitmapSource YoungPicBmp { get { return new BitmapImage(new Uri("{YoungPic}")); } }
                public string MediumPic { get; set; }
                public BitmapSource MediumPicBmp { get { return new BitmapImage(new Uri("{MediumPic}")); } }
                public string AdultPic { get; set; }
                public BitmapSource AdultPicBmp { get { return new BitmapImage(new Uri("{AdultPic}")); } }
                public bool SaltWater { get; set; }
                public bool FreshWater { get; set; }
                public bool Grasslands { get; set; }
                public bool Swamp { get; set; }
                public bool TropicalForest { get; set; }
                public bool Forest { get; set; }
                public bool ForestEdge { get; set; }
                public bool Sand { get; set; }
                public bool Coastal { get; set; }
                public bool RiverBorder { get; set; }
                public bool LakeBorder { get; set; }
                public bool Floodplain { get; set; }
            }


            public class WindowViewModel : INotifyPropertyChanged
            {
                public event PropertyChangedEventHandler PropertyChanged;
                //called when a property is changed
                protected void RaisePropertyChanged(string PropertyName)
                {
                    if (PropertyChanged != null)
                    {
                        PropertyChanged(this, new PropertyChangedEventArgs(PropertyName));
                    }
                }

                private ObservableCollection<LVData> _plantList = new ObservableCollection<LVData>();
                public ObservableCollection<LVData> lsvData
                {
                    get { return _plantList; }
                    set { _plantList = value; RaisePropertyChanged("lsvData"); }
                }

                public void PopulateDataFromXML(string filename)
                {

                    XDocument loaded = XDocument.Load(filename);

                    var Plants = from x in loaded.Descendants("Plants")
                                  select new
                                  {
                                      Name = x.Descendants("Name").First().Value,
                                      YoungPic = x.Descendants("YoungPic").First().Value,
                                      MediumPic = x.Descendants("MediumPic").First().Value,
                                      AdultPic = x.Descendants("AdultPic").First().Value,
                                      SaltWater = x.Descendants("SaltWater").First().Value,
                                      FreshWater = x.Descendants("FreshWater").First().Value,
                                      Grasslands = x.Descendants("Grasslands").First().Value,
                                      Swamp = x.Descendants("Swamp").First().Value,
                                      TropicalForest = x.Descendants("TropicalForest").First().Value,
                                      Forest = x.Descendants("Forest").First().Value,
                                      ForestEdge = x.Descendants("ForestEdge").First().Value,
                                      Sand = x.Descendants("Sand").First().Value,
                                      Coastal = x.Descendants("Coastal").First().Value,
                                      RiverBorder = x.Descendants("RiverBorder").First().Value,
                                      LakeBorder = x.Descendants("LakeBorder").First().Value,
                                      Floodplain = x.Descendants("Floodplain").First().Value
                                  };


                    foreach (var _plant in Plants)
                    {
                        _plantList.Add(new LVData {
                            Name = _plant.Name,
                            YoungPic = _plant.YoungPic,
                            MediumPic = _plant.MediumPic,
                            AdultPic = _plant.AdultPic,
                            SaltWater = Convert.ToBoolean(_plant.SaltWater),
                            FreshWater = Convert.ToBoolean(_plant.FreshWater),
                            Grasslands = Convert.ToBoolean(_plant.Grasslands),
                            Swamp = Convert.ToBoolean(_plant.Swamp),
                            TropicalForest = Convert.ToBoolean(_plant.TropicalForest),
                            Forest = Convert.ToBoolean(_plant.Forest),
                            Sand = Convert.ToBoolean(_plant.Sand),
                            Coastal = Convert.ToBoolean(_plant.Coastal),
                            RiverBorder = Convert.ToBoolean(_plant.RiverBorder),
                            LakeBorder = Convert.ToBoolean(_plant.LakeBorder),
                            Floodplain = Convert.ToBoolean(_plant.Floodplain)
                             
                        });

                    }
                    RaisePropertyChanged("lsvData");
                }

            }

    Can anybody find my mistake? I think the problem, now, is with the XAML and the binding because I'm seeing this error upon termination of the program:

    System.Windows.Data Error: 40 : BindingExpression path error: 'lsvData' property not found on 'object' ''PlantDisplay' (Name='')'. BindingExpression:Path=lsvData; DataItem='PlantDisplay' (Name=''); target element is 'ListView' (Name='listView1'); target property is 'ItemsSource' (type 'IEnumerable')



    • Edited by Zetar Friday, June 14, 2013 2:03 PM Added all XAML and added System error
    Thursday, June 13, 2013 5:15 PM

Answers

  • I think the problem is that you are using DisplayMemberBinding AND CellTemplate. It should be one or the other.

     

    Therefore the DisplayMemberPath is overriding the CellTemplate and just showing ToString() representation of the image, which is of course it's name.

    Remove the DisplayMemberPath, then the CellTemplate should kick in.

    Regards,
    Pete


    #PEJL Got a good solution? If you invest your time in coding an elegant/novel or large answer on these MSDN forums, why not copy it over to our beloved TechNet Wiki, for future generations to benefit from!

    • Marked as answer by Zetar Friday, June 14, 2013 8:32 PM
    Friday, June 14, 2013 8:22 PM
    Moderator

All replies

  • Hi Zetar

     

    You don't mention where the images are, how they're being stored, or if in the project, what the build action and copy setting is. I'm guessing they're in the file system or a URL?

     

    I have a project on MSDN Samples that shows various ways of referencing images.

    http://code.msdn.microsoft.com/Referencing-in-WPF-62ed6ea1

    Maybe one of these methods would work for you?

     

    Regards,
    Pete


    #PEJL Got a good solution? If you invest your time in coding an elegant/novel or large answer on these MSDN forums, why not copy it over to our beloved TechNet Wiki, for future generations to benefit from!


    Thursday, June 13, 2013 11:49 PM
    Moderator
  • I think you should use BitmapImage for the Image control instead of BitmapSource.

    Anson

    Friday, June 14, 2013 2:53 AM
  • The images are on disk and some are a resource. I've tried both methods.
    Friday, June 14, 2013 11:28 AM
  • I originally tried BitmapImage. Someone, on another forum, recently suggested BitmapSource.
    Friday, June 14, 2013 11:29 AM
  • Try to implement your property like this:

    public BitmapSource YoungPicBmp
        {
          get {
            System.Windows.Media.Imaging.BitmapImage img = new System.Windows.Media.Imaging.BitmapImage();
            img.BeginInit();
            img.UriSource = new Uri("image.png", UriKind.Relative);
            img.EndInit();
            return img;
          }
        }

    Friday, June 14, 2013 1:01 PM
  • Nice idea, and I thought it would work.

    Unfortunately, the results are the same:

    I really thought this might be it. Maybe it's something on the XAML side with the binding?

    Friday, June 14, 2013 1:10 PM
  • It should work if you have specified a CellTemplate for the GridViewColumn:

        <ListView ....>
          <ListView.View>
            <GridView>
              <GridViewColumn>
                <GridViewColumn.CellTemplate>
                  <DataTemplate>
                    <Image Source="{Binding YoungPicBmp}"/>
                  </DataTemplate>
                </GridViewColumn.CellTemplate>
              </GridViewColumn>
            </GridView>
          </ListView.View>
        </ListView>

    Friday, June 14, 2013 1:48 PM
  • I just editing the original post adding ALL XAML code. Using DataTemplate. Should I be using a CellTemplate instead?

    I also posted the error that is being thrown (after exit).

    Friday, June 14, 2013 2:07 PM
  • Now you are using a CellTemplate: <GridViewColumn Width="202" Header="Picture of Young Plant" DisplayMemberBinding="{Binding Path=YoungPic}" CellTemplate="{StaticResource YoungPicCell}" />

    Did you also try to implement the property according to my previous post? Then you should be able to see the actual picture assuming your bindings are configured properly.

    Friday, June 14, 2013 2:31 PM
  • Magnus, yes I implemented the previous post (the changes to get).

    You're suggesting that I change CellTemplate to

    <GridViewColumn.CellTemplate>
                  <DataTemplate>

    yes?

    I will try that next.

    I've had to do a bunch of reboots. Altova XMLSpy has glommed all my WinZip and Office document icons and converted it to their own! Still haven't got it back to where it was (even after deleting Altova XMLSpy!).

    Friday, June 14, 2013 3:39 PM
  • I'm going to paste the entire XAML code here; perhaps you can help me out because I'm really confused where you want this new XAML code to go (template? binding?). Do I have the DataTemplate(s) in the wrong section? I'm pretty new to WPF and XAML.

    Thanks in Advance!

    <Window x:Class="DinosaurIsland.PlantDisplay"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:DinosaurIsland"
        Title="Vegetation" Height="308" Width="1212" WindowStyle="SingleBorderWindow" 
        DataContext="{Binding RelativeSource={RelativeSource Self}}" Loaded="Window_Loaded">
        <Window.Resources>
            <DataTemplate x:Key="YoungPicCell">
                <StackPanel Orientation="Horizontal">
                    <Image Height="200" Width="200" Name="YoungPicture"  Stretch="None"  Source="{Binding YoungPicBmp}"    />
                </StackPanel>
            </DataTemplate>
            <DataTemplate x:Key="MediumPicCell">
                <StackPanel Orientation="Horizontal">
                    <Image Height="200" Width="200" Name="MediumPicture"  Stretch="None" Source="{Binding MediumPicBmp}" />
                </StackPanel>
            </DataTemplate>
            <DataTemplate x:Key="AdultPicCell">
                <StackPanel Orientation="Horizontal">
                    <Image Height="200" Width="200" Name="AdultPicture" Stretch="None" Source="{Binding Path=AdultPicBmp}" />
                </StackPanel>
            </DataTemplate>
    
            <DataTemplate x:Key="TerrainCell">
                <StackPanel Orientation="Vertical">
                    <CheckBox Content="Salt Water"  Name="SaltWaterCheckbox" IsThreeState="False" IsChecked="{Binding SaltWater}" />
                    <CheckBox Content="Fresh Water"  Name="FreshWaterCheckbox" IsThreeState="False" IsChecked="{Binding FreshWater}" />
                    <CheckBox Content="Grassland / Plains"  Name="GrasslandsCheckbox" IsThreeState="False"  IsChecked="{Binding Grasslands}" />
                    <CheckBox Content="Swamp"  Name="SwampCheckbox" IsThreeState="False" IsChecked="{Binding Swamp}" />
                    <CheckBox Content="Tropical Forest"  Name="TropicalForestCheckbox" IsThreeState="False"  IsChecked="{Binding TropicalForest}" />
                    <CheckBox Content="Forest"  Name="ForestCheckbox" IsThreeState="False" IsChecked="{Binding Forest}" />
                    <CheckBox Content="Forest Edge"  Name="ForestEdgeCheckbox" IsThreeState="False"  IsChecked="{Binding ForestEdge}" />
                    <CheckBox Content="Sand"  Name="SandCheckbox" IsThreeState="False" IsChecked="{Binding Sand}" />
                    <CheckBox Content="Coastal"  Name="CoastalCheckbox" IsThreeState="False" IsChecked="{Binding Coastal}" />
                    <CheckBox Content="River Border"  Name="RiverBorderCheckbox" IsThreeState="False" IsChecked="{Binding RiverBorder}" />
                    <CheckBox Content="LakeBorder"  Name="LakeBorderCheckbox" IsThreeState="False"  IsChecked="{Binding LakeBorder}" />
                    <CheckBox Content="Floodplain"  Name="FloodplainCheckbox" IsThreeState="False"  IsChecked="{Binding Floodplain}" />
                </StackPanel>
            </DataTemplate>
    
            <DataTemplate x:Key="PlacePlantsCell">
                <StackPanel Orientation="Vertical">
                    <Label Margin="10"  Content="Random" HorizontalAlignment="Center" ></Label>
                    <Slider Margin="10"  Width="190" Value="50" Orientation="Horizontal" HorizontalAlignment="Center" IsSnapToTickEnabled="True" Maximum="100" TickPlacement="BottomRight"  TickFrequency="5"> </Slider>
                    <Button Margin="10"  Content="Randomly Seed Plants" HorizontalAlignment="Center"  Height="23" Name="SeedButton" ></Button>
                </StackPanel>
            </DataTemplate>
        </Window.Resources>
    
        <DockPanel>
            <Grid>
                <ListView ItemsSource="{Binding Path=lsvData, Mode=TwoWay}" Name="listView1">
                    <ListView.View>
                        <GridView>
                            <GridViewColumn Width="152" Header="Name" DisplayMemberBinding="{Binding Path=Name}"  />
                            <GridViewColumn Width="202" Header="Picture of Young Plant" DisplayMemberBinding="{Binding Path=YoungPic}" CellTemplate="{StaticResource YoungPicCell}" />
                            <GridViewColumn Width="202" Header="Picture of Medium Plant"  DisplayMemberBinding="{Binding Path=MediumPic}" CellTemplate="{StaticResource MediumPicCell}" />
                            <GridViewColumn Width="202" Header="Picture of Adult Plant"  DisplayMemberBinding="{Binding Path=AdultPic}" CellTemplate="{StaticResource AdultPicCell}" />
                            <GridViewColumn Width="202" Header="Terrain / Environments" CellTemplate="{StaticResource TerrainCell}" />
                            <GridViewColumn Width="202" Header="Place Plants" CellTemplate="{StaticResource PlacePlantsCell}" />
                        </GridView>
                    </ListView.View>
                </ListView>
                <Button Content="New Plant"  DockPanel.Dock="Bottom"  Height="23" HorizontalAlignment="Left" Margin="160,240,0,0" Name="NewPlant" VerticalAlignment="Top" Width="75" Click="NewPlant_Click" />
                <Button Content="Save" DockPanel.Dock="Bottom"   Height="23" HorizontalAlignment="Center" Margin="1099,240,15,0" Name="SavePlant" VerticalAlignment="Top" Width="75" Click="SavePlant_Click"/>
                <Button Content="Load" DockPanel.Dock="Bottom" Height="23" HorizontalAlignment="Left" Margin="26,240,0,0" Name="LoadPlants" VerticalAlignment="Top"  Click="LoadPlants_Click" Width="75" /> 
            </Grid>
        </DockPanel>
    </Window>
    


    Friday, June 14, 2013 4:35 PM
  • I think the problem is that you are using DisplayMemberBinding AND CellTemplate. It should be one or the other.

     

    Therefore the DisplayMemberPath is overriding the CellTemplate and just showing ToString() representation of the image, which is of course it's name.

    Remove the DisplayMemberPath, then the CellTemplate should kick in.

    Regards,
    Pete


    #PEJL Got a good solution? If you invest your time in coding an elegant/novel or large answer on these MSDN forums, why not copy it over to our beloved TechNet Wiki, for future generations to benefit from!

    • Marked as answer by Zetar Friday, June 14, 2013 8:32 PM
    Friday, June 14, 2013 8:22 PM
    Moderator
  • Thanks!
    Friday, June 14, 2013 8:32 PM