-1

Basically I'm trying to put a result of a query into a file path, into the image source.

Updated code. Now I actually get the string I want but I still have trouble with interpolating it into the Uri constructor.

 Random rand = new Random();
            var nrand = rand.Next(1, 4);

            using (var db = new DungeonContext())
            {
                var query = db.Rooms.Where(b => b.RoomId == nrand).Select(b => b.RoomName);
                foreach(string name in query)
                {
                    nameOfRoom = name;
                }
            }

Somehow I have trouble setting images dir as Resources since I'm missing advancent properties for this folder.

roomScreen.Source = new BitmapImage(new Uri($"/images/{nameOfRoom}.png", UriKind.Relative));

Making Uri relative seemed to stop throwing exceptions, but the intended effect does not happen.

  • Does this - https://stackoverflow.com/questions/2887924/invalid-uri-the-format-of-the-uri-could-not-be-determined answer your question? – MBB May 30 '20 at 17:44
  • What is the value of `nameOfRoom`and where does the error come from, and when? Is it at compile, build, package or run time? I'm going to guess that you have a space in the value of `nameOfRoom` and the failure is at runtime? – teambanana May 30 '20 at 17:47
  • the exception is System.UriFormatException more pricesly: "{Incorrect URI indentification: can't detrmine the URI indetification format} " I'm paraphrasing a bit since I don't have english langage packk installed on this instance of VS. As for the exact vale of nameOfRoom, they're supposed to be either 1NE, 2NE, or 3NE – Redesigner May 30 '20 at 18:35
  • I haven't yet set them to Resource. I was thinking about it but I tried first with the method I was currently doing. – Redesigner May 30 '20 at 19:47
  • they are in the apllication directory. If I'm not being to specific I'm sorry, I'm not sure what's the correct way of calling it. – Redesigner May 30 '20 at 20:14

3 Answers3

2

The way you're creating the URI is correct. The trouble is that you're trying to use what is likely meant to be readable text (the name of a room) in a URI and as a flle name. You didn't specify what nameOfRoom is, so I can't tell exactly why it's invalid.

There are ways around it. You could look at this answer which explains how to remove invalid characters from a file name.

But the best solution is not to have the problem. Don't use the name of the room as a file name. Your question indicates that a room has an ID, which is apparently an integer. Using that instead would be much easier:

using (var db = new DungeonContext())
{
    room = db.Rooms.Where(b => b.RoomId == nrand);
}

and then

roomScreen.Source = new BitmapImage( new Uri($"/images/Room{room.RoomId}.png"));

If you want to use your code as-is, that's possible. When you do this:

nameOfRoom = db.Rooms.Where(b => b.RoomId == nrand).ToString();

you're calling ToString() on what is presumably a Room class. Unless you override that method, the result will always be the name of the class. (So it would be the same for every room.)

If you overrode the ToString method:

public override string ToString()
{
    return $"Room{RoomId}";
}

then calling room.ToString() would return "Room1" or "Room2", etc.

String interpolation calls ToString(), so in that case you could just do

roomScreen.Source = new BitmapImage( new Uri($"/images/{room}.png"));

That works. One downside is that it's not explicit. Someone reading that line of code might not know that Room.ToString() is also the value used to create a file name. You might also want to use the ToString() method differently.

If you wanted to be really explicit and clear, you could create an extension method like this:

public static class RoomFileNameExtensions
{
    public static string GetImageFileName(this Room room)
    {
        return $"Room{room.RoomId}.png";
    }
}

Now the Room class isn't responsible for knowing how file names are created. You could do this:

roomScreen.Source = new BitmapImage( new Uri($"/images/{room.GetImageFileName()}"));

You can use that both when creating the file and when reading the file. It ensures that both operations will determine the file name the same way.

Scott Hannen
  • 27,588
  • 3
  • 45
  • 62
  • well NameOfRoom is a string. Sorry for forgetting to mention it. And I'm using its name because I'm also planning to use it as an identifier for the rooms features. e. g. a room with the name 1NE has: 1 door, is normal, and is empty. Also I might have wrote the Linq statment wrong, because I wasn't trying to get the RoomId prop, but other prop called RoomName. – Redesigner May 30 '20 at 17:54
  • I know (it comes from calling `ToString()`. But it still depends on what that string is. You could also leave it coded exactly as it is, and override `ToString()` on the room class so that it returns a valid string. But if the ID uniquely identifies the room, and the name of the file needs to uniquely identify the file, it could make sense to just use the ID. – Scott Hannen May 30 '20 at 17:56
  • sorry for all this mess with my question. I figured out what I had problems with and worded it better. now my main question was regarding the URI constructor and I'm not sure how I can use interpolated string in the constructor since it returns errors for invali characters. I might not have understood what you meant, and that's why I'm asking this. – Redesigner May 31 '20 at 16:51
  • to clarify, does the folder containing the images actually needs to be named "resouces"? – Redesigner May 31 '20 at 17:11
  • It was just an example. I tried to use details from your question. The same applies regardless of the folder name. – Scott Hannen May 31 '20 at 17:18
  • understandable. continuing from my other question did I use invalid argument in Uri? should I have provided the full path, i.e. starting from the disk? – Redesigner May 31 '20 at 19:24
  • There are multiple answers to that. I don't know what the actual URI was because I don't know what the string was. You can use the debugger to see what the string is. It's also good to look at the documentation for .NET framework classes. You can highlight the `Uri` class and press F1, or google "Uri class .NET". – Scott Hannen Jun 01 '20 at 00:05
  • thanks for the help. I managed to figure out the issue by reading the documentation. – Redesigner Jun 01 '20 at 17:46
0

Apparently all I needed to do was add UriKInd.RelativeOrAbsolute to the constructor.

  • It sounds like the solution you found doesn't relate to the question. The way you include text in a URI doesn't change depending on whether it's absolute or relative. – Scott Hannen Jun 01 '20 at 18:00
  • @ScottHannen Well it fixed my issue. And I think it wasn't working correctly not because I interpolated the string wrong, but because the path was invalid and by changing its path value it fixed everything. If you think my answer doesn't answer the question. I could just leave it unanswered. – Redesigner Jun 05 '20 at 14:25
  • The idea is to make sure it helps the next person. If someone else is trying to figure out how to incorporate a variable into a URL, and then they google and find this, will it answer their question? – Scott Hannen Jun 05 '20 at 14:53
  • @ScottHannen I guess I phrashed my question inaccuretly. – Redesigner Jun 05 '20 at 15:01
-1

If it's in the project directory, utilizing the System.IO.Path namespace comes to mind - something like

Path.Combine(Environment.CurrentDirectory, $"/images/{nameOfRoom}.png")
Ben Sampica
  • 2,912
  • 1
  • 20
  • 25