简体   繁体   中英

C# WPF Array of nested classes with image

I am struggling to teach myself C#, and long googling has not turned up this answer:

I have a classes Rom, Game and Art. Rom.Game.Art is for images and is defined thus:

public class art
{
    public Image Screen { get; set; }
    public Image Marquis { get; set; }
    public Image Logo { get; set; }

    public art ()
    {
        BitmapImage Default_image = new BitmapImage();
        Default_image.BeginInit();
        Default_image.UriSource = new Uri(@"C:\Users\Major Major\Documents\Visual Studio 2013\Projects\Robin\Robin\images\bee_ace.png", UriKind.Absolute);
        Default_image.EndInit();

        this.Screen = new Image();
        this.Screen.Source = Default_image;
        this.Marquis = new Image();
        this.Marquis.Source = Default_image;
        this.Logo = new Image();
        this.Logo.Source = Default_image;
    }
}

I want to create an array of Roms, and populate the many nested properties and subclasses from a DataTable in a loop. Before I get into the loop, though, I just want to get a block of test code to work. The following works just fine:

        InitializeComponent();
        BitmapImage Image_0 = new BitmapImage();

        Image_0.BeginInit();
        Image_0.UriSource = new Uri(@"E:\Arcade\Art\Box\Intellivision\Congo Bongo.jpg", UriKind.Absolute);
        Image_0.EndInit();

        ROMS.Insert(0, new Rom());

        ROMS[0].Name = "Congo Bongo";
        ROMS[0].Game.Art.Screen.Source = Image_0;
        ROMS[0].Game.Date = "1983";
        ROMS[0].Game.Platform = "Intellivision";

        ROM_list.ItemsSource = ROMS;

My complaint is that, if I put this in a loop, all of the images in the array will be the same--they will be the last image entered. It seems the expression "ROMS[0].Game.Art.Screen.Source = Image_0;" ties ROMS[0].Game.Art.Screen.Source to the variable Image_0, rather than just transferring the value (this seems like surprising behavior to me, but no worries). So that in order to keep populating ROMS[j].Game.Art.Screen.Source, I have to create an array of BitmapImages separate from the ROM array as a reference. What I'd prefer is to instantiate(?) the BitmapImages within the array, like this:

        ROMS[0].Game.Art.Screen.Source = new BitmapImage();
        InitializeComponent();
        ROMS[0].Game.Art.Screen.Source.BeginInit();
        ROMS[0].Game.Art.Screen.Source.UriSource = new Uri(@"E:\Arcade\Art\Box\Intellivision\Congo Bongo.jpg", UriKind.Absolute);
        ROMS[0].Game.Art.Screen.Source.EndInit();

This doesn't work. Rom.Game.Art.Screen.Source is not a BitMapImage, and I cannot find the methods to assign an image to it.

So my questions, specifically: 1. Is there a way to assign an image source to ROMS[0].Game.Art.Screen.Source without creating a separate BitmapImage that lives on separately, or is that stupid?

  1. Is there a smarter way to do what I'm trying to do?

  2. Is there a reference to help me understand the relationships between the myriad image classes in C#?

Sorry for the wordy question, and thanks.

I think you should do some review about DataBinding. You will save more time.

You just need create something like the models:

ROM.Game.Art.Screen.Path ="meuPath.Jpg";

myItemSource = ROMS;

and in the end, do something like:

            <ItemsControl x:Name="myItemSource">
                    <TextBlock Text="{Binding ROM.Game.Art.Screen.Name}"/>
                    <Image Source="{Binding ROM.Game.Art.Screen.Path,Converter=MyConverterImageToPath"/>
            </ItemsControl>

You need to create a new instance of the BitMapImage for each of your array member. C# uses references if you assign an object to a variable.

ROMS[0].Game.Art.Screen.Source = Image_0;

here you are creating a reference to Image_0, if you do now something like ...

ROMS[1].Game.Art.Screen.Source = Image_0;

both roms[0] and roms[1] .screen.source referencing Image_0. If you do now something like:

ROMS[0].Game.Art.Screen.Source.UriSource = new Uri(@"E:\Arcade\Art\Box\Intellivision\Congo Bongo.jpg", UriKind.Absolute);

you update Image_0 and all your rom.screen.source are referencing to Image_0 and are updated

If you want to use Image_0 as base "image" for all, what you could do is call the .Clone() function of the bitmapImage, which creates a deep copy of the object (a new object, instead of a reference).

So somewhere in the begin you have:

InitializeComponent();
BitmapImage Image_0 = new BitmapImage();

Image_0.BeginInit();
Image_0.UriSource = new Uri(@"E:\Arcade\Art\Box\Intellivision\Congo Bongo.jpg", UriKind.Absolute);
Image_0.EndInit();

in your loop you have then

ROMS[i].Name = "Congo Bongo";
ROMS[i].Game.Art.Screen.Source = Image_0.Clone();
ROMS[i].Game.Date = "1983";
ROMS[i].Game.Platform = "Intellivision";

Thanks a lot for looking at this.

The deep copy concept is instructive, and gets me on the right track. But there is still no method that lets me modify ROMS[i].Game.Art.Screen.Source (the class of this Is Image.Source). It's interesting that I can assign a BitmapImage directly to an Image.Source, but then I cannot alter the BitmapImage by going through the class nest. In other words

ROMS[1].Game.Art.Screen.Source.UriSource

does not exist, even though ROMS[1].Game.Art.Screen.Source was set equal to a BitmapImage, which has a .UriSource.

So, using you comments as a starting point, I came up with the following, which will work in a loop, obviously with loop variables in place of each string:

        InitializeComponent();

        ROMS.Insert(0, new Rom());
        ROMS.Insert(1, new Rom());

        ROMS[0].Name = "Congo Bongo";
        ROMS[0].Game.Art.Screen.Source = new BitmapImage(new Uri(@"E:\Arcade\Art\Box\Intellivision\Congo Bongo.jpg", UriKind.Absolute));
        ROMS[0].Game.Date = "1983";
        ROMS[0].Game.Platform = "Intellivision";

        ROMS[1].Name = "Donkey Kong";
        ROMS[1].Game.Art.Screen.Source = new BitmapImage(new Uri(@"E:\Arcade\Art\Box\Intellivision\Donkey Kong.jpg", UriKind.Absolute));
        ROMS[1].Game.Date = "1982";
        ROMS[1].Game.Platform = "Intellivision";

        ROM_list.ItemsSource = ROMS;

Still, I have to create a new BitMapImage and Uri every time I modify Game.Image.Source. I wonder what happens to the old BitMapImage and Uri, which don't even have names and can't be modified. Do they just float around in memory for eternity, haunting the living variables? Am I still doing something silly?

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