Kodda WPF görüntü kaynağını ayarlama


325

Kodda bir WPF görüntünün kaynağı ayarlamaya çalışıyorum. Görüntü, projeye bir kaynak olarak gömülür. Örneklere bakarak aşağıdaki kodu buldum. Herhangi bir nedenden dolayı çalışmıyor - görüntü gösterilmiyor.

Hata ayıklama yoluyla akışın görüntü verilerini içerdiğini görebiliyorum. Yani ne yanlış?

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;

Simge şu şekilde tanımlanır: <Image x:Name="_icon" Width="16" Height="16" />


Görüntü yerel bir sürücüdeyse, <Image Source="some_fully_qualified_path">XAML'de asla başarısız olmaz.
Laurie Stearn

Tüm mesele, yolu bilmediğimiz ve belirlemek için koda ihtiyaç duyduğumuz. Windows GUI programlamasında yeni biri olarak, WinForms'un bu XAML saçmalığından daha çekici göründüğünü itiraf etmeliyim.
Alex Jansen

Yanıtlar:


416

Sizinle aynı sorunu yaşadıktan ve biraz okuma yaptıktan sonra çözümü keşfettim - Paket URI'leri .

Kodda aşağıdakileri yaptım:

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;

Veya daha kısa, başka bir BitmapImage yapıcısı kullanarak:

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

URI parçalara ayrılmıştır:

  • Yetki: application:///
  • Yol: Başvurulan bir derlemede derlenen kaynak dosyasının adı. Yol aşağıdaki biçime uygun olmalıdır:AssemblyShortName[;Version][;PublicKey];component/Path

    • AssemblyShortName: başvurulan derlemenin kısa adı.
    • ; Sürüm [isteğe bağlı]: başvurulan derlemenin kaynak dosyasını içeren sürümü. Bu, aynı kısa ada sahip iki veya daha fazla başvurulan derleme yüklendiğinde kullanılır.
    • ; PublicKey [isteğe bağlı]: başvurulan derlemeyi imzalamak için kullanılan ortak anahtar. Bu, aynı kısa ada sahip iki veya daha fazla başvurulan derleme yüklendiğinde kullanılır.
    • ; component: başvurulan derlemeye yerel derlemeden başvurulduğunu belirtir.
    • / Yol: başvurulan derlemenin proje klasörünün köküne göre yolu da dahil olmak üzere kaynak dosyasının adı.

Üç eğik çizgi application:yerine virgül konulmalıdır:

Not: Bir paket URI'sının yetki bileşeni, bir paketi işaret eden ve RFC 2396'ya uyması gereken katıştırılmış bir URI'dır. Ayrıca, "/" karakteri "," karakteri ve "%" gibi ayrılmış karakterlerle değiştirilmelidir. ve "?" kaçmalı. Ayrıntılar için OPC'ye bakın.

Ve elbette, resminizdeki oluşturma eylemini olarak ayarladığınızdan emin olun Resource.


Evet, bu biraz deneme yanılma sonrasında bulduğum çözümdü. Ayrıntılı açıklama için teşekkürler. Yanıt kabul edildi!
Torbjørn

Bunun neden gerekli olduğunu ve diğer cevapların benim için neden işe yaramadığını bilmiyorum ...
Torbjørn

bu konudaki diğer cevaplar ve diğer sorular da benim için işe yaramadı. Bu mükemmel çalışıyor. Teşekkürler.
Thomas Stock

9
Tamam, ancak XAML ayrıştırıcısının basit yol dizesini ImageSource'a dönüştürmek için kullandığı bazı yöntem veya sınıf yok mu? Bunu sadece kullanamaz mıydık?
Qwertie

1
Bu snippet'in, genellikle BitmapImage(Uri)BeginInit ve EndInit'i çağırmaktan kaçınmaya yardımcı olan, genellikle yapıcı varlığını göz ardı ettiği diğer gönderilere kopyalandığını görüyorum. Buraya ekledim.
Clemens

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

Bu, "Oluşturma Eylemi", "WpfApplication1" adlı bir derlemede "Kaynak" olarak ayarlanmış "Görüntüler" adlı bir klasöre "Untitled.png" adlı bir görüntü yükler.


16
Bunun için teşekkürler. Beni wpf için bir noob olarak tetikleyen bir sorun, görüntü çalışması için kaynak olarak işaretlenmelidir.
si618

4
Bu çözüm bana bir istisna verdi, bu yüzden Jared Harley'nin çözümünü denedim ve işe yaradı ...
Sangram Nandkhile

2
en önemli şey "UriKind.RelativeOrAbsolute" - diğer örnekler her zaman istisnalar attı
Sven

9
var uriSource = new Uri("Images/Untitled.png", UriKind.Relative);yeterli olurdu
Hamzeh Soboh

... ve çok daha kolay. Thanks
Hamzeh

74

Bu biraz daha az koddur ve tek bir satırda yapılabilir.

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

8
Bu kesinlikle en iyi yanıttır,
.NET'lerin

görüntünün yüksekliğini ve genişliğini ayarlamamız gerekiyorsa, yani icon.png? Çünkü _image.height ve _image.width kullanarak görüntü penceresini gerçek görüntüyü değil, yani icon.png olarak ayarlar.
secretgenes

41

Çok kolay:

Bir menü öğesinin görüntüsünü dinamik olarak ayarlamak için yalnızca aşağıdakileri yapın:

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

... ancak "icon.ico" her yerde bulunabilir (şu anda 'Kaynaklar' dizininde bulunur) ve Kaynak olarak bağlanması gerekir ...


2
Daha kısa = daha iyi. @ "/ Folder / image.png" olarak ayarlamak zorunda kaldı ama sonra iyi çalıştı. Teşekkürler!
11:59


@HaloMediaz yolu yanlış olabilir .... Örneğin Kaynaklarınız var ama yazabilirsiniz Kaynak
Rouzbeh Zarandi

Bu benim için çalıştı ve diğer cevaplardaki mutlak URI'lerden çok daha açıktı.
Psiloc

16

Bunu bir satıra da azaltabilirsiniz. Bu benim ana pencerem için Simge ayarlamak için kullandığım kod. .İco dosyasının İçerik olarak işaretlendiğini ve çıktı dizinine kopyalandığını varsayar.

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

16

En basit yol:

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

15

Denedin mi:

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

13

Bu benim yolum:

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);
    }
}

Kullanımı:

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

8

Görüntü yolunu dinamik olarak ayarlayan bir örnek (kaynak olarak oluşturmak yerine disk üzerinde bir yerde bulunan görüntü):

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;
}

Simgeler Üzerine Düşünceler ...

İlk olarak, Icon özelliğinin yalnızca bir görüntü içerebileceğini düşünürdünüz. Ama aslında her şeyi içerebilir! Programlı Imageolarak bir görüntünün yolu ile doğrudan bir dizeye özelliği ayarlamak için çalışırken yanlışlıkla bu keşfetti . Sonuç, görüntüyü değil, yolun gerçek metnini göstermesiydi!

Bu, simge için bir resim yapmak zorunda kalmamanıza bir alternatif sağlar, ancak basit bir "simge" görüntülemek için bunun yerine sembol yazı tipiyle metin kullanın. Aşağıdaki örnekte "floppydisk" sembolü içeren Wingdings yazı tipi kullanılmıştır. Bu sembol gerçekten <XAML'de özel bir anlamı olan karakterdir , bu yüzden &lt;bunun yerine kodlanmış sürümü kullanmalıyız. Bu bir rüya gibi çalışıyor! Aşağıda, menü öğesinde bir simge olarak bir floppydisk sembolü gösterilmektedir:

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

Soru: " Görüntü, projeye bir kaynak olarak gömülü " yanıtını verin: " İşte kaynak olarak oluşturmak yerine disk üzerinde bir yerde bulunan bir örnek [görüntü için] ."
dakika

7

Resminiz bir ResourceDictionary'te depolanmışsa, görüntüyü yalnızca bir kod satırı ile yapabilirsiniz:

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

6

Ayrıca daha basit bir yol var. Görüntü XAML'ye kaynak olarak yüklüyse ve söz konusu kod söz konusu XAML içeriğinin arkasındaki kodsa:

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

4

Çerçeveyi bir VisualBrush'a koyun:

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

brush.Visual = frame;

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

VisualBrush'ı GeometryDrawing'e yerleştirin

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;

Şimdi GeometryDrawing'i bir DrawingImage içine yerleştirin:

new DrawingImage(drawing);

Bunu görüntünün kaynağına yerleştirin ve voilà!

Yine de çok daha kolay yapabilirsiniz:

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

Ve kodda:

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

LOL! İlk zorlaştırdığınızda neden kolaylaştırıyorsunuz :) Ama kabul etmeden önce basit çözümünüzü deneyeceğim ...
Torbjørn

Aslında bu bana hiç yardımcı olmadı. Belki aptal değilim :( Şu anda daha yakından bakmak için zamanım yok (evcil hayvan projesi) Geri döndüğümde daha fazla cevap istiyorum :)
Torbjørn

3

Ayrıca daha basit bir yol var. Görüntü XAML'ye kaynak olarak yüklüyse ve söz konusu kod söz konusu XAML için kod arkasıysa:

İşte bir XAML dosyası için kaynak sözlüğü - önemsediğiniz tek satır "PosterBrush" anahtarıyla ImageBrush - kodun geri kalanı sadece bağlamı göstermek

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

        </ResourceDictionary>
    </UserControl.Resources>

Şimdi, arkadaki kodda, bunu yapabilirsiniz

ImageBrush posterBrush = (ImageBrush)Resources["PosterBrush"];

2

Kaynak simgelerine ve görüntülere gömülü bir görüntü nasıl yüklenir (Arcturus'un düzeltilmiş sürümü):

Resim içeren bir düğme eklemek istediğinizi varsayalım. Ne yapmalısın?

  1. Proje klasörü simgelerine ekleyin ve ClickMe.png resmini buraya yerleştirin
  2. 'ClickMe.png' özelliğinin özelliklerinde, 'BuildAction'ı' Kaynak 'olarak ayarlayın
  3. Derlenmiş derleme adınızın 'Company.ProductAssembly.dll' olduğunu varsayalım.
  4. Şimdi resmimizi XAML'ye yükleme zamanı

    <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>

Bitti.


2

WPF için yeniyim, ancak .NET'te değil.

.NET 3.5 (Visual Studio 2010) "WPF Özel Denetim Kitaplığı Projesi" için bir PNG dosyası eklemek ve bir görüntü devralınan denetimin arka plan olarak ayarlamak için beş saat geçirdim.

URI'lerle ilgili hiçbir şey işe yaramadı. Neden bir kaynak dosyasından, IntelliSense aracılığıyla bir URI almak için hiçbir yöntem olduğunu düşünemiyorum belki:

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

Çok sayıda URI denedim ve ResourceManager ve Assembly'nin GetManifest yöntemleri ile oynadım, ancak hepsi istisnalar veya NULL değerler vardı.

İşte benim için çalışan kodu pot:

// 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;

3
Bence sorun, WPF'nin kaynakları resx dosyalarına koymanın geleneksel yaklaşımını "sevmediği". Bunun yerine, görüntüyü doğrudan projenize eklemeniz ve Build Action özelliğini Kaynak olarak ayarlamanız gerekir. İki yaklaşım arasındaki farkın (fiziksel dosya biçimi olarak) ne olduğunu bilmiyorum.
Qwertie

1
Yapım Eyleminin İçerik
Olduğundan

1

Zaten bir akışınız varsa ve biçimi biliyorsanız, böyle bir şey kullanabilirsiniz:

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

1

Biraz özledin.

Herhangi bir derlemeden katıştırılmış bir kaynak almak için, burada belirttiğim gibi dosya adınızla derleme adını belirtmeniz gerekir:

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;

BeginInit (), WPF'de görünmüyor.
Myosotis

Aşağıdaki bağlantıyı kontrol edebilirsiniz msdn.microsoft.com/en-us/library/…
maulik kansara
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.