How do I make an image stretch to fill in this WPF

2020-03-03 07:55发布

问题:

When my program displays an image which is smaller than the Image GUI object defined in XAML, it does not get stretched to fit as I would like it to. For example a 256x256 image only occupies the upper left quadrant of my 512x512 Image GUI object. I am puzzled because I have set Stretch="Fill" in the XAML code. What else do I need to be doing? Any help with the code (see below) would be greatly appreciated.

XAML code defining the GUI

  <Window x:Class="MyProgram.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MyProgarm" Height="900" Width="890" Name="mainWindow" Icon="Icon.ico" MouseDown="mouseDown">
        <Grid Name="mainGrid" Background="#FFEBE7F0" Width="800.10">
          <Border Margin="139,32,0,0" Name="border1" Height="512" VerticalAlignment="Top" HorizontalAlignment="Left" Width="512" Background="#F0D4D0D0" />
          <Border Margin="138,602,0,0" Name="border2" Height="256" VerticalAlignment="Top" HorizontalAlignment="Left" Width="256" Background="#F0D4D0D0" />
          <Border Margin="400,602,0,0" Name="border3" Height="256" VerticalAlignment="Top" HorizontalAlignment="Left" Width="256" Background="#F0D4D0D0" />
          <Image Margin="135,32,0,0" Name="imagePanel1" Stretch="Fill" HorizontalAlignment="Left" Width="512" MouseMove="imagePanelAxl_MouseMove" Height="512" VerticalAlignment="Top" Canvas.Left="-135" Canvas.Top="-32">
          </Image>

Code I use to draw the image:

byte[] myColorImage=// 256x256 RGB image loaded from disk

int W=256;
int H=256;  // dimensions of myColorImage
// Use multiple cores
image.Dispatcher.BeginInvoke(
System.Windows.Threading.DispatcherPriority.Normal,
new Action<byte[]>(
      delegate(byte[] myColorImage_IN)
      {
          const int dpi = 96;

          BitmapSource bmpsrc = BitmapSource.Create(W, H, dpi, dpi, PixelFormats.Bgr24, null, myColorImage_IN, W * 3);
          image.Source = bmpsrc;


      }
  ), myColorImage);

回答1:

Instead of Image use Image Brush that will do the work for you

 <Border.Background>
            <ImageBrush x:Name="image" Stretch="UniformToFill"/>
 </Border.Background>

And in the Code Behind you can Set

   image.ImageSource = bmpsrc; // if you can give the URL of the File Located on the Disk


回答2:

As many people said above here is the code for using ImageBrush. Which also sets the image while MouseOver. Thought it might helps new users.

<Grid.Resources>
    <ImageBrush x:Key="AddButtonImageBrush" ImageSource="/DemoApp;component/Resources/AddButton.png" Stretch="Uniform"/>

    <Style x:Key="AddButtonImageStyle" TargetType="{x:Type Button}">
        <Setter Property="Background" Value="{StaticResource AddButtonImageBrush}"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Button}">
                    <Border Background="{TemplateBinding Background}">
                        <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
        <Style.Triggers>
            <Trigger Property="IsMouseOver" Value="True">
                <Setter Property="Background"  Value="{StaticResource AddButtonImageBrush}"/>
            </Trigger>
        </Style.Triggers>
    </Style>
</Grid.Resources>

<Button Content="If Text is also Required" Style="{StaticResource AddButtonImageStyle}"/>


回答3:

If you known the URI of the image on the disk you should use the ImageBrush control.



回答4:

I have a few comments on your code:

And in your XAML you name your image:

imagePanel1

and in codebehind you used:

image

In the image tag in the XAML you said:

Canvas.Left="-135" Canvas.Top="-32"

This image tag is not in a canvas,, it is in a grid.


In the code behind you use the dispatcher to make things use multiple cores?

The dispatcher is used to execute thing from other threads into the UI thread. And if image (from which you use the dispatcher) is also in the UI thread (what I guess it is since it is a UI object) then this wont make your application use multiple cores.


If you set the image margin to 0 and remove the horizontal and vertical alignment. Also remove the width and height. Then your image should completely fill your window.

Can you test this for me.


And you can always use and Uri to set the bitmapsource to the file on your system.

BitmapImage bi3 = new BitmapImage();
bi3.BeginInit();
bi3.UriSource = new Uri("smiley_stackpanel.PNG", UriKind.Relative); //instead you can also use Urikind.Absolute
bi3.EndInit();
imagePanel1.Stretch = Stretch.Fill;
imagePanel1.Source = bi3;