WPF görüntü kaynakları


408

Çoğunlukla web'den ve biraz Windows Forms geçmişinden geliyorum. Yeni bir proje için WPF kullanacağız. WPF uygulaması, açıklama amacıyla 10-20 küçük simge ve resme ihtiyaç duyacaktır. Bunları mecliste gömülü kaynaklar olarak depolamayı düşünüyorum. Bu doğru yol mu?

XAML'de bir Görüntü denetiminin görüntüyü katıştırılmış bir kaynaktan yüklemesi gerektiğini nasıl belirleyebilirim?

Yanıtlar:


473

Görüntüyü birden çok yerde kullanacaksanız, görüntü verilerini yalnızca bir kez belleğe yüklemeye ve ardından tüm Imageöğeler arasında paylaşmaya değer .

Bunu yapmak için BitmapSource , bir yerde kaynak olarak a oluşturun :

<BitmapImage x:Key="MyImageSource" UriSource="../Media/Image.png" />

Ardından, kodunuzda şöyle bir şey kullanın:

<Image Source="{StaticResource MyImageSource}" />

Benim durumumda, ben ayarlamak zorunda bulundu Image.pngbirikimi harekete sahip dosyayı Resourcesadece ziyade Content. Bu, görüntünün derlenmiş montajınız içinde taşınmasına neden olur.


6
Bunu dinamik olarak yapmak mümkün müdür? Başlangıçta yüklemek istediğim farklı sayıda görüntüm varsa, görüntü başına BitmapSource oluşturabilir ve bunlara yukarıdaki gibi başvurabilir miyim?
Becky Franklin

2
@Becky - Evet, Xaml'de bunlara başvurmak isterseniz, anahtarları derleme zamanında bileceğinizi varsayarak , DynamicResourcebiçimlendirme uzantısını kullanmanız gerekebilir StaticResource. WPF'de çalışma zamanında kaynak sözlükleri oluşturabilirsiniz. Aslında, bir Xaml belgesi yüklediğinizde olan şey budur, sadece eşdeğer C # 'ı görmemenizdir.
Drew Noakes

9
Vurduğum bir şey: resim kaynağınızı bir kaynak sözlüğüne eklerseniz, bileşeniniz için XAML'deki bu resim sözlüğüne başvurmayı unutmayın. Şuna benzer: <UserControl.Resources> <ResourceDictionary> <ResourceDictionary.MergedDictionaries> <ResourceDictionary Source = "Dictionary1.xaml" /> </ResourceDictionary.MergedDictionaries> </ResourceDictionary> </UserControl.Resources>
Dan Mitchell

4
Genellikle eklemek Width="{Binding Source.PixelWidth, RelativeSource={RelativeSource Self}}" için Imageaksi sık sık görüntüler grotesquely nedense büyütülüyor alma gördüğünüz gibi, (örneğin 16x16 simgeler görünüyor gibi 200x200 piksel o şeye gergin).
VEYA Haritacı

5
BitmapImage başvurulan bir derlemenin Resourcedictionary bildirilirse, UriSource bunun çalışması için bir packURI olması gerektiğini buldum. Aksi takdirde, görüntüyü VS'de xaml düzenleyicinizde görebileceğinizi, ancak hata ayıklama sırasında görüntü göremeyeceğinizi göreceksiniz. Paket URIS: msdn.microsoft.com/en-au/library/aa970069(v=vs.100).aspx
başarısız programlama

174

Resim, video vb.Kullanmanın en iyi uygulaması olarak buldum:

  • Dosyalarınızı değiştirme "Yapı eylem" için "İçerik" . Dizin oluşturmak için Kopyala'yı işaretlediğinizden emin olun .
    • Çözüm Gezgini penceresindeki "Sağ Tıklama" menüsünde bulunur.
  • Görüntü Kaynağı aşağıdaki biçimde:
    • "/ « MontajAdınız » ; bileşen /« YourPath »/ « YourImage.png » "

Misal

<Image Source="/WPFApplication;component/Images/Start.png" />

Yararları:

  • Dosyalar montajın içine yerleştirilmez.
    • Kaynak Yöneticisi çok fazla kaynakla (derleme zamanında) bazı bellek taşması sorunlarını ortaya çıkaracaktır.
  • Montajlar arasında çağrılabilir.

36
Aynı yaklaşım, kaynağı derlemeye katıştırırsanız çalışır, ancak "Derleme Eylemi" ni "Kaynak" olarak ayarlamanız gerekir.
Ashley Davis

5
Çalışır, teşekkürler. Diğerleri için bir not: "bileşen" gereklidir "olduğu gibi", "Görüntüler" projedeki png'nin göreceli yoludur. Köke yerleştirilen görüntü "<Image Source =" / WPFApplication; bileşen / Start.png "/>" olacaktır
Badiboy

3
Bunun C # ile nasıl yapılacağına bir örnek iyi olurdu. (Bu geçerli bir URI değildir, bu yüzden bir BitmapImage oluştururken kullanılamaz.)
Vaccano

5
Peki, dosya Gömülü Kaynak olarak ayarlanmışsa bunu nasıl yaparsınız? Bu işe yaramıyor gibi görünüyor. Ve görüntüyü projeme iki kez dahil etmek istemiyorum. (Zaten gömülü bir kaynak olarak kullanıyorum.)
BrainSlugs83

2
Nerede ve nasıl "bileşen" yola girer. Bu bazı şartnamenin bir parçası mı?
Triynko

46

Bazı insanlar bunu kodla yapmayı ve cevap alamamayı soruyor.

Saatlerce arama yaptıktan sonra çok basit bir yöntem buldum, örnek bulamadım ve bu yüzden burada benim resimlerle çalışan madeni paylaşıyorum. (benimki bir .gif idi)

Özet:

ImageSource "hedefleri" gibi görünüyor bir BitmapFrame döndürür.

kullanın:

doGetImageSourceFromResource ("[YourAssemblyNameHere]", "[YourResourceNameHere]");

Yöntem:

static internal ImageSource doGetImageSourceFromResource(string psAssemblyName, string psResourceName)
{
    Uri oUri = new Uri("pack://application:,,,/" +psAssemblyName +";component/" +psResourceName, UriKind.RelativeOrAbsolute);
    return BitmapFrame.Create(oUri);
}

Öğrenmeler:

Deneyimlerimden, paket dizesi sorun değil, akışlarınızı kontrol edin ve özellikle ilk kez okurken işaretçiyi dosyanın sonuna ayarladıysanız ve tekrar okumadan önce sıfıra ayarlamanız gerekir.

Umarım bu parça benim için olsaydı saatlerce kurtarır!


44

Kodunda Freq.png, görüntümün klasörde bulunduğu Iconsve şu şekilde tanımlandığı yürütme derlemesine bir kaynak yüklemek için Resource:

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

Ayrıca bir işlev yaptım:

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

Kullanım (işlevi bir ResourceHelper sınıfına koyduğunuz varsayımı):

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

Not : WPF'deki MSDN Paketi URI'larına bakın :
pack://application:,,,/ReferencedAssembly;component/Subfolder/ResourceFile.xaml


yeni Uri geçersiz URI atar: Geçersiz bağlantı noktası belirtildi.
Steve

Sorun yaratan uri var mı?
Eric Ouellet

1
benimkiyle aynı uri, benimki WinP tarafından barındırılan bir WPF içinde koşuyordu. Ve yeni Uri dediğimde "paket" şeması henüz kaydedilmedi.
Steve

1
Hata! Büyük olasılıkla, barındırılan WPF'nin kazanılması ile ilgili. Üzgünüm. Düzeltmeye çalışmayacağım çünkü çok yaygın bir kullanım olmadığını düşünüyorum. İyi şanslar!
Eric Ouellet

Benim durumumda, kullanmak new Uri(@"pack://application:,,,/" + pathInApplication)da hile yaptı.
Adam Calvet Bohl

40

Evet, doğru yol.

Kaynak dosyasındaki görüntüyü yalnızca yolu kullanarak kullanabilirsiniz:

<Image Source="..\Media\Image.png" />

Görüntü dosyasının derleme eylemini "Kaynak" olarak ayarlamanız gerekir.


1
Bunun için teşekkürler. Bir ImageSource ile benzer bir şey yapmanın bir yolu var mı, temelde görüntüyü bir kez bir kaynak sözlüğüne yüklüyor. Bu yaklaşımın görüntü verilerini birden çok kez belleğe yüklediğinden korkuyorum.
Drew Noakes

2
Kodunuzu yeniden düzenlemeniz gerektiğinde bu bir karışıklık olacaktır. Xaml belgeniz ad alanını değiştirirse, tüm görüntü referanslarını manuel olarak değiştirmeniz gerekecektir. Drew Noakes tarafından açıklanan yöntem çok daha pürüzsüz ve bakımı kolaydır.
Kasper Holdum


5
  1. Visual Studio 2010 Professional SP1.
  2. .NET Framework 4 İstemci Profili.
  3. PNG resmi proje özelliklerine kaynak olarak eklendi.
  4. Kaynaklar klasöründeki yeni dosya otomatik olarak oluşturulur.
  5. Kaynak olarak ayarlanmış eylem oluşturun.

Bu benim için çalıştı:

<BitmapImage x:Key="MyImageSource" UriSource="Resources/Image.png" />

3

Karışımı kullanıyorsanız , bunu kolaylaştırmak ve Kaynak özniteliği için doğru yolu bulmakta sorun yaşamamak için , görüntüyü Proje panelinden tasarımcıya sürükleyip bırakın.


3

Evet, doğru yol. Kaynak dosyasındaki görüntüleri bir yol kullanarak kullanabilirsiniz:

<StackPanel Orientation="Horizontal">
    <CheckBox  Content="{Binding Nname}" IsChecked="{Binding IsChecked}"/>
    <Image Source="E:\SWorking\SharePointSecurityApps\SharePointSecurityApps\SharePointSecurityApps.WPF\Images\sitepermission.png"/>
    <TextBlock Text="{Binding Path=Title}"></TextBlock>
</StackPanel>

-5

Aşağıdakiler çalıştı ve ayarlanacak görüntüler özelliklerdeki kaynaklardır:

    var bitmapSource = Imaging.CreateBitmapSourceFromHBitmap(MyProject.Properties.Resources.myImage.GetHbitmap(),
                                      IntPtr.Zero,
                                      Int32Rect.Empty,
                                      BitmapSizeOptions.FromEmptyOptions());
    MyButton.Background = new ImageBrush(bitmapSource);
img_username.Source = bitmapSource;

5
Suç yok ama kötü uygulama gibi kokuyor.
ShloEmi
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.