środa, 11 stycznia 2012

WPF: Lepiej umieścić obrazek w resources niż bawić się ścieżkami. [PL]

Ostatnio pod wpisem: "[WPF 3D] Malujemy scenę 3D pędzlem" dostałem w ramach komentarza pytanie związane z obrazkami w WPF i ścieżkami w nich. Nie jest to wielki problem, ale postaram się odpowiedzieć.




Otóż problem wyglądał następująco: czytelnik tworzył pędzel przy pomocy kodu:
ImageBrush brush = new ImageBrush(new BitmapImage(new Uri(BaseUriHelper.GetBaseUri(this), "Images/test.png"))); 
Niestety tak utworzony pędzel nie zawsze generował obraz, taki jak to było oczekiwane. Jak temu zaradzić. Otóż najlepiej odejść od korzystania z takich ścieżek do obrazków lub przynajmniej ograniczyć ilość miejsc, w których takie ścieżki powstają.
Według mnie najwygodniej dodać obrazek do zasobów, np. w następujący sposób:
Wtedy w aplikacji możemy w zasobach napisać w XAML'u:
        <BitmapImage x:Key="MyImageSource" UriSource="./ImageResources/logo_zielone_tlo.jpg" />
        <ImageBrush  x:Key="MyImageBrush" ImageSource="{StaticResource ResourceKey=MyImageSource}"/>
I ostatecznie stworzyć dla przykładu następujące okno:
Powyższe okno powstało przy pomocy następującego kodu XAML:
<Window x:Class="WpfApplication_resources_tests.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Window1" Height="200" Width="200">
    <Window.Resources>
        <BitmapImage x:Key="MyImageSource" UriSource="./ImageResources/logo_zielone_tlo.jpg" />
        <ImageBrush  x:Key="MyImageBrush" ImageSource="{StaticResource ResourceKey=MyImageSource}"/>
    </Window.Resources>
    <Grid>
        <Label Background="{StaticResource ResourceKey=MyImageBrush}" Width="50" Height="50" 
               VerticalAlignment="Top" HorizontalAlignment="Left"/>
        <Viewport3D Name="mainViewport">
            <Viewport3D.Camera>
                <PerspectiveCamera FarPlaneDistance="100" LookDirection="-1,-1,-1"
              UpDirection="0,1,0" NearPlaneDistance="1" Position="3,3,3" FieldOfView="70" />
            </Viewport3D.Camera>
            <ModelVisual3D>
                <ModelVisual3D.Content>
                    <DirectionalLight Color="White" Direction="-1,-1,-1" />
                </ModelVisual3D.Content>
            </ModelVisual3D>
            <ModelVisual3D>
                <ModelVisual3D.Content>
                    <GeometryModel3D>
                        <GeometryModel3D.Geometry>
                            <MeshGeometry3D Positions="-2 -2 0  2 -2 0  -2 2 0  2 2 0"
                            Normals="0 0 1  0 0 1  0 0 1  0 0 1" TextureCoordinates="0 1  1 1  0 0  1 0   "
                            TriangleIndices="0 1 2  1 3 2" />
                        </GeometryModel3D.Geometry>
                        <GeometryModel3D.Material>
                            <DiffuseMaterial Brush="{StaticResource ResourceKey=MyImageBrush}" />
                        </GeometryModel3D.Material>
                    </GeometryModel3D>
                </ModelVisual3D.Content>
            </ModelVisual3D>
        </Viewport3D>
    </Grid>
</Window>
Promuj

2 komentarze:

  1. Nie, obrazków nie trzyma się w zasobach. Ikony, czasem, jak potrzeba, jeden, dwa obrazki, ale nie więcej. One są za duże - EXE-k puchnie, robi się bałagan, trzeba rekompilować, by zmienić obrazek, a i krótsze nie jest.

    Tą linijkę równie dobrze można zapisać jako:

    ImageBrush brush = new ImageBrush(new BitmapImage(new Uri("Images/test.png", UriKind.Relative)));

    Można to wpakować w jakąś statyczną klasę helpera, by nie pisać nie wiadomo ile razy.

    OdpowiedzUsuń
  2. Dzięki za komentarz!

    Choć przyznam, że jednak nie do końca się z nim zgadzam, a dlaczego? Przeczytaj w nowym wpisie: WPF: o zasobach (resources) coś więcej.

    OdpowiedzUsuń

Posty powiązane / Related posts