Frage

Ich habe ein seltsames Problem mit WPF, ich habe Bilder von der Platte zur Laufzeit zu laden und sie zu einem StackView Container hinzufügen. Allerdings wurden die Bilder nicht angezeigt. Nach einigen Debuggen fand ich den Trick, aber es ist wirklich keinen Sinn. Ich habe eine kleine Demo-Anwendung, das Problem zu identifizieren:

Erstellen

ein neues WPF-Projekt und Einfügen von Code wie folgt:

XAML:

<Window x:Class="wpfBug.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300" Loaded="Window_Loaded">
    <StackPanel Name="sp">
    </StackPanel>
</Window>

xaml.cs, Paste unter Standard usings:

namespace wpfBug
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            Image i = new Image();
            BitmapImage src = new BitmapImage();
            src.BeginInit();
            src.UriSource = new Uri("picture.jpg", UriKind.Relative);
            src.EndInit();
            i.Source = src;
            i.Stretch = Stretch.Uniform;
            //int q = src.PixelHeight;        // Image loads here
            sp.Children.Add(i);
        }
    }
}

Kopieren Sie ein Bild in die bin / Debug-Ordner und nennen es 'picture.jpg'

Dieses Programm zeigt nichts an, es sei denn, die Kommentarzeile unkommentiert ist.

Kann mir jemand erklären, was ich falsch mache, oder warum dies geschieht? Wenn Sie das Bild entfernen und das Programm ausführen es erzeugt eine Ausnahme auf der ‚int q = ...‘ Linie. Wenn diese Zeile des Programm läuft ohne Ausnahmen kommentiert wird, auch wenn kein Bild vorhanden ist. Laden ein Bild nur dann, wenn nessesary Sinn macht, aber dann sollte das Bild geladen werden, wenn ich die Bildsteuerung auf den Stackpanel hinzuzufügen.

Jede Iden?

Edit:. By the way, wenn Sie das Bild als eine Ressource, die 'int q = ..' Linie ist nicht erforderlich hinzufügen

War es hilfreich?

Lösung

Es ist, weil die Schöpfung verzögert wurde. Wenn Sie das Bild wollen sofort geladen werden, können Sie einfach diesen Code in die init-Phase hinzu.

src.CacheOption = BitmapCacheOption.OnLoad;

wie folgt aus:

src.BeginInit();
src.UriSource = new Uri("picture.jpg", UriKind.Relative);
src.CacheOption = BitmapCacheOption.OnLoad;
src.EndInit();

Andere Tipps

Code-Ressource in der Ausführung Assembly zu laden, wo mein Bild ‚Freq.png‘ im Ordner war „Icons“ und definiert als „Ressource“.

        this.Icon = new BitmapImage(new Uri(@"pack://application:,,,/" 
             + Assembly.GetExecutingAssembly().GetName().Name 
             + ";component/" 
             + "Icons/Freq.png", UriKind.Absolute)); 

Ich habe auch eine Funktion, wenn jemand es möchte ...

/// <summary>
/// Load a resource WPF-BitmapImage (png, bmp, ...) from embedded resource defined as 'Resource' not as 'Embedded resource'.
/// </summary>
/// <param name="pathInApplication">Path without starting slash</param>
/// <param name="assembly">Usually 'Assembly.GetExecutingAssembly()'. If not mentionned, I will use the calling assembly</param>
/// <returns></returns>
public static BitmapImage LoadBitmapFromResource(string pathInApplication, Assembly assembly = null)
{
    if (assembly == null)
    {
        assembly = Assembly.GetCallingAssembly();
    }

    if (pathInApplication[0] == '/')
    {
        pathInApplication = pathInApplication.Substring(1);
    }
    return new BitmapImage(new Uri(@"pack://application:,,,/" + assembly.GetName().Name + ";component/" + pathInApplication, UriKind.Absolute)); 
}

Verbrauch:

        this.Icon = ResourceHelper.LoadBitmapFromResource("Icons/Freq.png");

Das ist ein merkwürdiges Verhalten, und obwohl ich nicht in der Lage bin zu sagen, warum dies geschieht, kann ich einige Optionen empfehlen.

Als erstes wird eine Beobachtung. Wenn Sie das Bild als Inhalt in VS enthalten und kopieren Sie sie in das Ausgabeverzeichnis, Ihr Code funktioniert. Wenn das Bild als None in VS markiert ist und Sie kopieren es vorbei, es funktioniert nicht.

Lösung 1: Filestream

Das Bitmap Objekt akzeptiert einen UriSource oder Stream als Parameter. Lassen Sie uns verwenden Stream statt.

        FileStream stream = new FileStream("picture.png", FileMode.Open, FileAccess.Read);
        Image i = new Image();
        BitmapImage src = new BitmapImage();
        src.BeginInit();
        src.StreamSource = stream;
        src.EndInit();
        i.Source = src;
        i.Stretch = Stretch.Uniform;
        panel.Children.Add(i);

Das Problem: Strom bleibt offen. Wenn Sie es am Ende dieses Verfahrens schließen, wird das Bild nicht auf. Das bedeutet, dass die Datei bleibt auf dem System schreib gesperrt.

Lösung 2: Memorystream

Dies ist im Grunde Lösung 1, aber Sie die Datei in einen Speicher-Stream lesen und diesen Speicher-Stream als Argument übergeben.

        MemoryStream ms = new MemoryStream();
        FileStream stream = new FileStream("picture.png", FileMode.Open, FileAccess.Read);
        ms.SetLength(stream.Length);
        stream.Read(ms.GetBuffer(), 0, (int)stream.Length);

        ms.Flush();
        stream.Close();

        Image i = new Image();
        BitmapImage src = new BitmapImage();
        src.BeginInit();
        src.StreamSource = ms;
        src.EndInit();
        i.Source = src;
        i.Stretch = Stretch.Uniform;
        panel.Children.Add(i);

Nun können Sie die Datei auf dem System ändern, wenn dies etwas, das Sie benötigen.

Sie könnten versuchen, Handler für verschiedene Veranstaltungen von Bitmap Befestigung:

Sie könnten sagen, Sie ein wenig über das, was vor sich geht, so weit das Bild betrifft.

Hier ist die Extension-Methode ein Bild von URI zu laden:

public static BitmapImage GetBitmapImage(
    this Uri imageAbsolutePath,
    BitmapCacheOption bitmapCacheOption = BitmapCacheOption.Default)
{
    BitmapImage image = new BitmapImage();
    image.BeginInit();
    image.CacheOption = bitmapCacheOption;
    image.UriSource = imageAbsolutePath;
    image.EndInit();

    return image;
}

Beispiel für die Verwendung:

Uri _imageUri = new Uri(imageAbsolutePath);
ImageXamlElement.Source = _imageUri.GetBitmapImage(BitmapCacheOption.OnLoad);

So einfach ist das!

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top