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" />
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:
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
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.
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.
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;
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 ...
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));
Einfachster Weg:
var uriSource = new Uri("image path here");
image1.Source = new BitmapImage(uriSource);
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;
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"))
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;
}
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 <
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"><</Label>
</MenuItem.Icon>
</MenuItem>
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;
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);
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" };
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"];
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?
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.
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;
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;
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];
}