it-swarm.com.de

Einstellen der WPF-Bildquelle im Code

Ich versuche, die Quelle eines WPF-Bildes im Code festzulegen. Das Bild wird als Ressource in das Projekt eingebettet. Anhand von Beispielen habe ich den folgenden Code gefunden. Aus irgendeinem Grund funktioniert es nicht - das Bild wird nicht angezeigt.

Durch das Debuggen kann ich sehen, dass der Stream die Bilddaten enthält. Also, was ist falsch?

Assembly asm = Assembly.GetExecutingAssembly();
Stream iconStream = asm.GetManifestResourceStream("SomeImage.png");
PngBitmapDecoder iconDecoder = new PngBitmapDecoder(iconStream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
ImageSource iconSource = iconDecoder.Frames[0];
_icon.Source = iconSource;

Das Icon ist ungefähr so ​​definiert: <Image x:Name="_icon" Width="16" Height="16" />

309
Torbjørn

Nachdem ich dasselbe Problem wie Sie hatte und etwas gelesen hatte, entdeckte ich die Lösung - Pack URIs .

Ich habe im Code Folgendes getan:

Image finalImage = new Image();
finalImage.Width = 80;
...
BitmapImage logo = new BitmapImage();
logo.BeginInit();
logo.UriSource = new Uri("pack://application:,,,/AssemblyName;component/Resources/logo.png");
logo.EndInit();
...
finalImage.Source = logo;

Oder kürzer mit einem anderen BitmapImage-Konstruktor:

finalImage.Source = new BitmapImage(
    new Uri("pack://application:,,,/AssemblyName;component/Resources/logo.png"));

Die URI ist in Teile aufgeteilt:

  • Autorität: application:///
  • Pfad: Der Name einer Ressourcendatei, die in eine referenzierte Assembly kompiliert wird. Der Pfad muss dem folgenden Format entsprechen: AssemblyShortName[;Version][;PublicKey];component/Path

    • AssemblyShortName: Der Kurzname für die referenzierte Assembly.
    • ; Version [optional]: Die Version der Assembly, auf die verwiesen wird und die die Ressourcendatei enthält. Dies wird verwendet, wenn zwei oder mehr Assemblys mit demselben Kurznamen geladen werden, auf die verwiesen wird.
    • ; PublicKey [optional]: Der öffentliche Schlüssel, mit dem die referenzierte Assembly signiert wurde. Dies wird verwendet, wenn zwei oder mehr Assemblys mit demselben Kurznamen geladen werden, auf die verwiesen wird.
    • ; component: gibt an, dass auf die Assembly verwiesen wird, auf die von der lokalen Assembly verwiesen wird.
    • / Pfad: Der Name der Ressourcendatei, einschließlich ihres Pfads, relativ zum Stammverzeichnis des Projektordners der referenzierten Assembly.

Die drei Schrägstriche nach application: müssen durch Kommas ersetzt werden:

Hinweis: Die Berechtigungskomponente eines Pack-URI ist ein eingebetteter URI, der auf ein Paket verweist und RFC 2396 entsprechen muss. Außerdem muss das Zeichen "/" durch das Zeichen "," und reservierte Zeichen wie "%" ersetzt werden. und "?" muss entkommen. Einzelheiten finden Sie im OPC.

Und stellen Sie natürlich sicher, dass Sie die Erstellungsaktion für Ihr Image auf Resource setzen.

398
Jared Harley
var uriSource = new Uri(@"/WpfApplication1;component/Images/Untitled.png", UriKind.Relative);
foo.Source = new BitmapImage(uriSource);

Dadurch wird ein Bild mit dem Namen "Untitled.png" in einen Ordner mit dem Namen "Images" geladen, dessen "Build Action" in einer Assembly mit dem Namen "WpfApplication1" auf "Resource" gesetzt ist.

170
Simon

Dies ist etwas weniger Code und kann in einer einzelnen Zeile erfolgen.

string packUri = "pack://application:,,,/AssemblyName;component/Images/icon.png";
_image.Source = new ImageSourceConverter().ConvertFromString(packUri) as ImageSource;
73
Alex B

Sehr leicht:

Führen Sie die folgenden Schritte aus, um das Bild eines Menüelements dynamisch festzulegen:

MyMenuItem.ImageSource = 
    new BitmapImage(new Uri("Resource/icon.ico",UriKind.Relative));

... wohingegen "icon.ico" sich überall befinden kann (derzeit befindet es sich im 'Resources'-Verzeichnis) und als Ressource verknüpft sein muss ...

41
A Bothe

Sie können dies auch auf eine Zeile reduzieren. Dies ist der Code, mit dem ich das Symbol für mein Hauptfenster festgelegt habe. Es wird davon ausgegangen, dass die ICO-Datei als Inhalt markiert ist und in das Ausgabeverzeichnis kopiert wird.

 this.Icon = new BitmapImage(new Uri("Icon.ico", UriKind.Relative));
16
Payson Welch

Einfachster Weg:

var uriSource = new Uri("image path here");
image1.Source = new BitmapImage(uriSource);
15
Hasan

Hast du es versucht:

Assembly asm = Assembly.GetExecutingAssembly();
Stream iconStream = asm.GetManifestResourceStream("SomeImage.png");
BitmapImage bitmap = new BitmapImage();
bitmap.BeginInit();
bitmap.StreamSource = iconStream;
bitmap.EndInit();
_icon.Source = bitmap;
14
Andrew Myhre

Das ist mein Weg:

internal static class ResourceAccessor
{
    public static Uri Get(string resourcePath)
    {
        var uri = string.Format(
            "pack://application:,,,/{0};component/{1}"
            , Assembly.GetExecutingAssembly().GetName().Name
            , resourcePath
        );

        return new Uri(uri);
    }
}

Verwendungszweck:

new BitmapImage(ResourceAccessor.Get("Images/1.png"))
11
IlPADlI

Hier ist ein Beispiel, das den Image-Pfad dynamisch festlegt (Image befindet sich irgendwo auf dem Datenträger und wird nicht als Ressource erstellt):

if (File.Exists(imagePath))
{
    // Create image element to set as icon on the menu element
    Image icon = new Image();
    BitmapImage bmImage = new BitmapImage();
    bmImage.BeginInit();
    bmImage.UriSource = new Uri(imagePath, UriKind.Absolute);
    bmImage.EndInit();
    icon.Source = bmImage;
    icon.MaxWidth = 25;
    item.Icon = icon;
}

Überlegungen zu Icons ...

Der erste Gedanke ist, dass die Icon-Eigenschaft nur ein Bild enthalten kann. Aber es kann tatsächlich alles enthalten! Das habe ich zufällig entdeckt, als ich programmgesteuert versucht habe, die Eigenschaft Image direkt auf eine Zeichenfolge mit dem Pfad zu einem Bild festzulegen. Das Ergebnis war, dass es nicht das Bild zeigte, sondern den tatsächlichen Text des Pfades!

Dies führt zu einer Alternative, bei der kein Bild für das Symbol erstellt werden muss, sondern stattdessen Text mit einer Symbolschrift verwendet wird, um ein einfaches "Symbol" anzuzeigen. Das folgende Beispiel verwendet die Wingdings-Schriftart , die ein "Disketten" -Symbol enthält. Dieses Symbol ist wirklich das Zeichen <, das in XAML eine besondere Bedeutung hat, daher müssen wir stattdessen die codierte Version &lt; verwenden. Das funktioniert wie ein Traum! Die folgende Abbildung zeigt ein Diskettensymbol als Symbol im Menüelement:

<MenuItem Name="mnuFileSave" Header="Save" Command="ApplicationCommands.Save">
  <MenuItem.Icon>
    <Label VerticalAlignment="Center" HorizontalAlignment="Center" FontFamily="Wingdings">&lt;</Label>
  </MenuItem.Icon>
</MenuItem>
8
awe

Wenn Ihr Bild in einem ResourceDictionary gespeichert ist, können Sie es mit nur einer Codezeile ausführen:

MyImage.Source = MyImage.FindResource("MyImageKeyDictionary") as ImageSource;
6
Hollyroody

Es gibt auch einen einfacheren Weg. Wenn das Bild als Ressource in die XAML geladen ist und der betreffende Code der Code-Behind für diesen XAML-Inhalt ist:

Uri iconUri = new Uri("pack://application:,,,/ImageNAme.ico", UriKind.RelativeOrAbsolute);
NotifyIcon.Icon = BitmapFrame.Create(iconUri);
5
Bharat Thanki

Setzen Sie den Rahmen in einen VisualBrush:

VisualBrush brush = new VisualBrush { TileMode = TileMode.None };

brush.Visual = frame;

brush.AlignmentX = AlignmentX.Center;
brush.AlignmentY = AlignmentY.Center;
brush.Stretch = Stretch.Uniform;

Versetzen Sie den VisualBrush in GeometryDrawing

GeometryDrawing drawing = new GeometryDrawing();

drawing.Brush = brush;

// Brush this in 1, 1 ratio
RectangleGeometry rect = new RectangleGeometry { Rect = new Rect(0, 0, 1, 1) };
drawing.Geometry = rect;

Fügen Sie nun die GeometryDrawing in ein DrawingImage ein:

new DrawingImage(drawing);

Platziere dies auf deiner Bildquelle und voilà!

Sie könnten es jedoch viel einfacher machen:

<Image>
    <Image.Source>
        <BitmapImage UriSource="/yourassembly;component/YourImage.PNG"></BitmapImage>
    </Image.Source>
</Image>

Und im Code:

BitmapImage image = new BitmapImage { UriSource="/yourassembly;component/YourImage.PNG" };
3
Arcturus

Es gibt auch einen einfacheren Weg. Wenn das Bild als Ressource in die XAML geladen ist und der betreffende Code der Code hinter dieser XAML ist:

Hier ist das Ressourcenwörterbuch für eine XAML-Datei - die einzige Zeile, die Sie interessiert, ist der ImageBrush mit dem Schlüssel "PosterBrush" - der Rest des Codes dient nur dazu, den Kontext anzuzeigen

<UserControl.Resources>
        <ResourceDictionary>
            <ImageBrush x:Key="PosterBrush" ImageSource="..\Resources\Images\EmptyPoster.jpg" Stretch="UniformToFill"/>

        </ResourceDictionary>
    </UserControl.Resources>

Im Code dahinter können Sie dies einfach tun

ImageBrush posterBrush = (ImageBrush)Resources["PosterBrush"];
3
Mark Mullin

So laden Sie ein Bild aus eingebetteten Ressourcensymbolen und Bildern (korrigierte Version von Arcturus):

Angenommen, Sie möchten eine Schaltfläche mit einem Bild hinzufügen. Was sollte man tun?

  1. Fügen Sie zu den Projektordnersymbolen hinzu und platzieren Sie das Bild ClickMe.png hier
  2. Setzen Sie in den Eigenschaften von "ClickMe.png" "BuildAction" auf "Ressource".
  3. Angenommen, Ihr kompilierter Assemblyname lautet "Company.ProductAssembly.dll".
  4. Jetzt ist es Zeit, unser Image in XAML zu laden

    <Button Width="200" Height="70">
      <Button.Content>
        <StackPanel>
          <Image Width="20" Height="20">
            <Image.Source>
              <BitmapImage UriSource="/Company.ProductAssembly;component/Icons/ClickMe.png"></BitmapImage>
              </Image.Source>
          </Image>
          <TextBlock HorizontalAlignment="Center">Click me!</TextBlock>
        </StackPanel>
      </Button.Content>
    </Button>
    

Getan.

2
Siarhei Kuchuk

Ich bin neu in WPF, aber nicht in .NET.

Ich habe fünf Stunden lang versucht, einem "WPF Custom Control Library Project" in .NET 3.5 (Visual Studio 2010) eine PNG-Datei hinzuzufügen und diese als Hintergrund für ein von einem Bild geerbtes Steuerelement festzulegen.

Nichts, was mit URIs zu tun hatte, funktionierte. Ich kann mir nicht vorstellen, warum es keine Methode gibt, um einen URI aus einer Ressourcendatei über IntelliSense abzurufen, vielleicht als:

Properties.Resources.ResourceManager.GetURI("my_image");

Ich habe viele URIs ausprobiert und mit ResourceManager und den GetManifest-Methoden von Assembly gespielt, aber es gab nur Ausnahmen oder NULL-Werte.

Hier gebe ich den Code ein, der für mich funktioniert hat:

// Convert the image in resources to a Stream
Stream ms = new MemoryStream()
Properties.Resources.MyImage.Save(ms, ImageFormat.Png);

// Create a BitmapImage with the stream.
BitmapImage bitmap = new BitmapImage();
bitmap.BeginInit();
bitmap.StreamSource = ms;
bitmap.EndInit();

// Set as source
Source = bitmap;
2
JoanComasFdz

Du hast nur ein bisschen verpasst.

Um eine eingebettete Ressource von einer Assembly zu erhalten, müssen Sie den Assemblynamen zusammen mit Ihrem Dateinamen wie hier erwähnt angeben:

Assembly asm = Assembly.GetExecutingAssembly();
Stream iconStream = asm.GetManifestResourceStream(asm.GetName().Name + "." + "Desert.jpg");
BitmapImage bitmap = new BitmapImage();
bitmap.BeginInit();
bitmap.StreamSource = iconStream;
bitmap.EndInit();
image1.Source = bitmap;
1
maulik kansara

Wenn Sie bereits einen Stream haben und das Format kennen, können Sie Folgendes verwenden:

static ImageSource PngStreamToImageSource (Stream pngStream) {
    var decoder = new PngBitmapDecoder(pngStream,
        BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
    return decoder.Frames[0];
}
1
user166390