Ustawianie źródła obrazu WPF w kodzie

Próbuję ustawić źródło obrazu WPF w kodzie. Obraz jest osadzony jako zasób w projekcie. Patrząc na przykłady wymyśliłem poniższy kod. Z jakiegoś powodu to nie działa - obraz nie pojawia się.

Po debugowaniu widzę, że strumień zawiera dane obrazu. Co się stało?

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;

Ikona jest zdefiniowana w następujący sposób: <Image x:Name="_icon" Width="16" Height="16" />

Author: Arcturus, 2008-12-08

18 answers

Po tym samym problemie co ty i poczytaniu, odkryłem rozwiązanie - Pack Uri .

Zrobiłem w kodzie:

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;

Lub krótszy, używając innego konstruktora BitmapImage:

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

URI jest podzielone na części:

  • władza: application:///
  • Path: nazwa pliku zasobu, który jest kompilowany do zestawu, do którego odnosi się odwołanie. Ścieżka musi być zgodna z następującym formatem: AssemblyShortName[;Version][;PublicKey];component/Path

    • AssemblyShortName: krótka nazwa odnoszącego się zestawu.
    • ; Version [opcjonalne]: wersja asemblacji, do której odnosi się plik zasobu. Jest to używane, gdy ładowane są dwa lub więcej odwołanych zespołów o tej samej krótkiej nazwie.
    • ;PublicKey[ opcjonalne]: klucz publiczny, który został użyty do podpisania odwołanego zestawu. Jest to używane, gdy ładowane są dwa lub więcej odwołanych zespołów o tej samej krótkiej nazwie.
    • ;Składnik: określa, że Zgromadzenie, do którego się odnosi, jest odwołane z lokalnego zgromadzenia.
    • / Path: nazwa pliku zasobu, w tym jego ścieżki, względem katalogu głównego projektu, do którego odnosi się zgromadzenie.

Trzy ukośniki po {[4] } należy zastąpić przecinkami:

Uwaga: Organ składowy URI pakietu jest wbudowanym URI, który wskazuje na pakiet i musi być zgodny z RFC 2396. Dodatkowo znak " / " musi zastępuje się znakiem",", i zastrzeżonych znaków, takich jak "%" i "?"musi uciec. # Patrz OPC po szczegóły.

I oczywiście upewnij się, że ustawiłeś akcję budowania na obrazie na Resource.

 427
Author: Jared Harley,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-07 06:49:17
var uriSource = new Uri(@"/WpfApplication1;component/Images/Untitled.png", UriKind.Relative);
foo.Source = new BitmapImage(uriSource);

Spowoduje to załadowanie obrazu o nazwie " Bez tytułu.png "w folderze o nazwie "Images" z jego "Build Action" ustawionym na "Resource" w złożeniu o nazwie "WpfApplication1".

 177
Author: Simon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-06-09 11:36:50

Jest to nieco mniej kodu i można to zrobić w jednej linii.

string packUri = "pack://application:,,,/AssemblyName;component/Images/icon.png";
_image.Source = new ImageSourceConverter().ConvertFromString(packUri) as ImageSource;
 76
Author: Alex B,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-06 17:47:13

Bardzo proste:

Aby dynamicznie ustawić obraz elementu menu, wykonaj tylko następujące czynności:

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

...natomiast " ikona.ico "może być zlokalizowane wszędzie (obecnie znajduje się w katalogu' Resources') I musi być połączone jako zasób...

 47
Author: A Bothe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-15 10:25:34

Najprostszy sposób:

var uriSource = new Uri("image path here");
image1.Source = new BitmapImage(uriSource);
 17
Author: Hasan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-19 12:43:19

Można również zmniejszyć to do jednej linii. Jest to kod, którego użyłem, aby ustawić ikonę dla mojego głównego okna. Zakłada, że ... plik ico jest oznaczony jako zawartość i jest kopiowany do katalogu wyjściowego.

 this.Icon = new BitmapImage(new Uri("Icon.ico", UriKind.Relative));
 16
Author: Payson Welch,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-02-13 17:09:08

Czy próbowałeś:

Assembly asm = Assembly.GetExecutingAssembly();
Stream iconStream = asm.GetManifestResourceStream("SomeImage.png");
BitmapImage bitmap = new BitmapImage();
bitmap.BeginInit();
bitmap.StreamSource = iconStream;
bitmap.EndInit();
_icon.Source = bitmap;
 15
Author: Andrew Myhre,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-09 22:37:41

This is my way:

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

Użycie:

new BitmapImage(ResourceAccessor.Get("Images/1.png"))
 13
Author: IlPADlI,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-14 06:22:52

Oto przykład, który dynamicznie ustawia ścieżkę obrazu (obraz znajduje się gdzieś na dysku, a nie buduje jako zasób):

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

Refleksje na temat ikon...

Po pierwsze, można by pomyśleć, że właściwość Icon może zawierać tylko obraz. Ale może zawierać wszystko! Odkryłem to przypadkowo, gdy programowo próbowałem ustawić właściwość Image bezpośrednio na łańcuch ze ścieżką do obrazu. Rezultatem było to, że nie pokazywał obrazu, ale rzeczywisty tekst ścieżki!

Prowadzi to do alternatywy, aby nie tworzyć obrazu dla ikony, ale zamiast tego używać tekstu z czcionką symbolu, aby wyświetlić prostą "ikonę". W poniższym przykładzie użyto czcionki Wingdings , która zawiera symbol "floppydisk". Ten symbol jest tak naprawdę znakiem <, który ma specjalne znaczenie w XAML, więc musimy użyć zakodowanej wersji &lt;. To działa jak sen! Poniżej przedstawiono symbol dyskietki jako ikonę w menu pozycja:

<MenuItem Name="mnuFileSave" Header="Save" Command="ApplicationCommands.Save">
  <MenuItem.Icon>
    <Label VerticalAlignment="Center" HorizontalAlignment="Center" FontFamily="Wingdings">&lt;</Label>
  </MenuItem.Icon>
</MenuItem>
 8
Author: awe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-19 12:25:00

Jeśli twój obraz jest przechowywany w ResourceDictionary, możesz to zrobić tylko jedną linijką kodu:

MyImage.Source = MyImage.FindResource("MyImageKeyDictionary") as ImageSource;
 8
Author: Hollyroody,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-19 12:45:25

Jest też prostszy sposób. Jeśli obraz jest załadowany jako zasób w XAML, a kod, o którym mowa, jest kodem-behind dla tej zawartości XAML:

Uri iconUri = new Uri("pack://application:,,,/ImageNAme.ico", UriKind.RelativeOrAbsolute);
NotifyIcon.Icon = BitmapFrame.Create(iconUri);
 6
Author: Bharat Thanki,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-19 12:32:13

Umieść ramkę w pędzlu wizualnym:

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

brush.Visual = frame;

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

Umieść VisualBrush w 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;

Teraz umieść GeometryDrawing w rysunku:

new DrawingImage(drawing);
Umieść to na swoim źródle obrazu i voila!

Możesz to zrobić o wiele łatwiej:

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

I w kodzie:

BitmapImage image = new BitmapImage { UriSource="/yourassembly;component/YourImage.PNG" };
 5
Author: Arcturus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-19 12:23:43

Jest też prostszy sposób. Jeśli obraz jest załadowany jako zasób w XAML, a dany kod jest kodem dla tego XAML:

Oto słownik zasobów dla pliku XAML - jedyną linijką, na której ci zależy, jest ImageBrush z kluczem "PosterBrush" - reszta kodu jest po prostu po to, aby pokazać kontekst

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

        </ResourceDictionary>
    </UserControl.Resources>

Teraz, w kodzie za, można po prostu zrobić to

ImageBrush posterBrush = (ImageBrush)Resources["PosterBrush"];
 3
Author: Mark Mullin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-19 12:27:06

Jak załadować obraz z osadzonych w zasobach ikon i obrazów (poprawiona wersja Arcturus):

Załóżmy, że chcesz dodać przycisk z obrazem. Co powinieneś zrobić?

  1. Dodaj do folderu projektu ikony i umieść obraz ClickMe.png tutaj
  2. we właściwościach ' ClickMe.png', Ustaw 'BuildAction ' na'Resource'
  3. Załóżmy, że nazwa Twojego skompilowanego zestawu to ' Company.Montaż produktu.dll".
  4. Teraz czas załadować nasz obraz w XAML

    <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>
    
Zrobione.
 2
Author: Siarhei Kuchuk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-19 12:28:59

Jestem nowy w WPF, ale nie w .NET.

Spędziłem pięć godzin próbując dodać plik PNG do projektu "WPF Custom Control Library Project" W. NET 3.5 (Visual Studio 2010) i ustawić go jako tło kontroli dziedziczonej obrazem.

Nic względnego z URI nie działało. Nie mogę sobie wyobrazić, dlaczego nie ma metody, aby uzyskać URI z pliku zasobów, poprzez IntelliSense, może jako:

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

Próbowałem wiele Uri i grałem z ResourceManager i Assembly ' S GetManifest metody, ale wszystkie były wyjątkami lub wartościami NULL.

Tutaj wrzuciłem kod, który mi zadziałał:

// 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
Author: JoanComasFdz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-19 12:31:21

Jeśli masz już strumień i znasz format, możesz użyć czegoś takiego:

static ImageSource PngStreamToImageSource (Stream pngStream) {
    var decoder = new PngBitmapDecoder(pngStream,
        BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
    return decoder.Frames[0];
}
 1
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-04-11 08:14:43

Po prostu trochę przegapiłeś.

Aby uzyskać osadzony zasób z dowolnego zestawu, musisz wspomnieć nazwę zestawu z nazwą pliku, jak wspomniałem tutaj:

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
Author: maulik kansara,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-19 12:44:26

Oto, jeśli chcesz zlokalizować go obok pliku wykonywalnego (względnego od pliku wykonywalnego)

img.Source = new BitmapImage(new Uri(AppDomain.CurrentDomain.BaseDirectory + @"\Images\image.jpg", UriKind.Absolute));
 0
Author: Donovan Phoenix,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-10-11 19:36:03