i need to create the context menu from code behind in WPF.
Everything works great except the Icon, i set the MenuItem icon like this
Dim tsmi As New MenuItem() With {
.Header = cmd.Name,
.Icon = cmd.Icon,
.Tag = cmd
}
where cmd.Icon is a System.Drawing.Image.
What i get instead of the Icon is the string System.Drawing.Image where it should be the Image.
Can anyone help?
System.Drawing.Image is from WinForms, what you need is a System.Windows.Controls.Image.
You can make one like this:
New Image() With {.Source = New BitmapImage(New Uri("pack://application:,,,/Your.Assembly.Name;component/Images/image.png"))}
...where you have a file called image.png (marked with Build Action=Resource) in a folder Images in the assembly Your.Assembly.Name.dll.
The MenuItem documentation shows this XAML:
<MenuItem Header="New">
<MenuItem.Icon>
<Image Source="data/cat.png"/>
</MenuItem.Icon>
</MenuItem>
So you can clearly use a WPF Image control for the icon. The documentation for the Image.Source property provides a link to a topic entitled "How to: Use the Image Element" and it includes this code example:
' Create Image Element
Dim myImage As New Image()
myImage.Width = 200
' Create source
Dim myBitmapImage As New BitmapImage()
' BitmapImage.UriSource must be in a BeginInit/EndInit block
myBitmapImage.BeginInit()
myBitmapImage.UriSource = New Uri("C:\Documents and Settings\All Users\Documents\My Pictures\Sample Pictures\Water Lilies.jpg")
' To save significant application memory, set the DecodePixelWidth or
' DecodePixelHeight of the BitmapImage value of the image source to the desired
' height or width of the rendered image. If you don't do this, the application will
' cache the image as though it were rendered as its normal size rather then just
' the size that is displayed.
' Note: In order to preserve aspect ratio, set DecodePixelWidth
' or DecodePixelHeight but not both.
myBitmapImage.DecodePixelWidth = 200
myBitmapImage.EndInit()
'set image source
myImage.Source = myBitmapImage
That pretty much gives you everything you need. I have never used any of these types or members before. I just spent some time reading the relevant documentation.
Related
I'm trying to assign a background to my WPF window.
I have a .jpg in bin\debug\StoredData\wallpaper.jpg
(I want to obtain the .jpg from there).
I came to putting this code inside the .cs file (newly created file):
InitializeComponent();
ImageBrush myBrush = new ImageBrush();
myBrush.ImageSource =
new BitmapImage(new Uri("\\StoredData\\login_wallpaper.jpg", UriKind.Absolute));
this.Background = myBrush;
But I get a "Invalid URI: The format of the URI could not be determined" message.
What should I change?
\StoredData\login_wallpaper.jpg is a relative URI. You can either change the UriKind to UriKind.Relative, or enter an absolute URI, depending on what behavior you want.
I'm trying to use a RadDesktopAlert from Telerik and I need to set an Icon to it.
So, I did this :
Dim bi As New BitmapImage
bi.BeginInit()
bi.UriSource = New Uri("pack://application:,,,/Resources/questions1.png")
bi.EndInit()
alert.Icon = bi
alert.IconColumnWidth = 75
But my alert don't have any icon, it sounds like that it can't find the resource... Build action is set to "Resource" for my file.
Can I have help please ?
Thanks !
This should work, provided that the image file is in folder "Resources" in your Visual Studio project, and that its Build Action is set to Resource:
Dim bitmap As New BitmapImage(New Uri("pack://application:,,,/Resources/questions1.png"))
Dim image As New Image() With {.Source = bitmap}
alert.Icon = image
In WPF, I'm trying to load many (thousands) of images into a ListBox WrapPanel.
I'm attempting to load the images similar to how a Windows Explorer window does.
So far I have my code which loads all the images' name, location (as tag), and a placeholder image to speed up load time:
Dim ofd As New Microsoft.Win32.OpenFileDialog()
ofd.Multiselect = True
ofd.Filter = "JPEG|*.jpg"
If ofd.ShowDialog() Then
For Each f In ofd.FileNames
Items.Add(New With {.img = New BitmapImage(New Uri("pack://application:,,,/Resources/PlaceholderPhoto.png")), .nam = Path.GetFileNameWithoutExtension(f), .tag = f})
Next
'The name of my ObservableCollection is Items'
lstboxPhotos.ItemsSource = Items
End If
That part is fine. What I'm trying to do after is load the images' thumbnails dynamically (one-by-one). I'm doing this so the user can interact with and see how many images are available while the thumbnails are loading. I've tried a couple different things - a background worker, dispatcher, and separate thread.
The code I'm using to load the images is below:
'i came from me doing a for..next for each image in Items collection'
Dim bmp As New BitmapImage()
bmp.BeginInit()
bmp.DecodePixelWidth = 90
bmp.DecodePixelHeight = 60
bmp.CacheOption = BitmapCacheOption.OnLoad
bmp.UriSource = New Uri(Items.Item(i).tag, UriKind.Absolute)
bmp.EndInit()
Items.Item(i).img = bmp
I've search all over the internet. I'm honestly not sure what direction to take in order to do what I'm needing to.
Let me know if I need to clarify anything else. Thank you in advance! :)
Edit:
Okay so referring to this article, using the 2nd answer I got the items to load one at a time. It loads all of the items' names just fine, but seems to stop loading the images after about 40 items.
If anyone could shed light on why it might cease loading the thumbnails, but continue loading the items' names that would be a great help! Thanks!
You can do that quickly and easily using the built in TypeConverter that converts string file paths into ImageSource objects. Take this simple example that will show thumbnails of all of the images in your Pictures folder:
public ObservableCollection<string> FilePaths { get; set; }
...
FilePaths = new ObservableCollection<string>(Directory.GetFiles(
Environment.GetFolderPath(Environment.SpecialFolder.MyPictures)));
...
<ItemsControl ItemsSource="{Binding FilePaths}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Image Source="{Binding}" Width="100" Stretch="Uniform" />
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
In this example, each Image.Source property is data bound directly with one of the file paths in the FilePaths collection.
Okay I know it's been a while, but I wanted to post what I ended up doing.
First, I loaded all the image names into the ListBox normally using an ObservableCollection with a temporary image:
Dim Items As New ObservableCollection(Of Object)
Dim Files() As String
...
For Each f In Files
Items.Add(New With {.img = New BitmapImage(New Uri("/Resources/Photo.png")), .name = f})
Next
lbPhotos.ItemsSource = Items
Then I used a BackgroundWorker to replace each placeholder image with the actual image:
Private WithEvents bw As New BackgroundWorker
Private Sub bw_DoWork(ByVal sender As Object, ByVal e As DoWorkEventArgs) Handles bw.DoWork
...
For i = 0 To Items.Count - 1
If bw.CancellationPending Then
e.Cancel = True
Else
Dim n As String = Items(i).name
Dim t As String = Items(i).tag
Dim bmp As New BitmapImage
bmp.BeginInit()
bmp.UriSource = New Uri(PathToImage, UriKind.Absolute)
bmp.EndInit()
bmp.Freeze()
Dispatcher.BeginInvoke(Sub()
Items.RemoveAt(i)
Items.Insert(i, New With {.img = bmp, .name = n})
End Sub)
End If
Next
End Sub
That allows for the user to interact with the UI while the images load.
Each WPF Image Control has RenderTransform Property that sets Scale, Skew, Rotate and many more Transformation to Images. After Calling RenderTransform Property, How to get Rendered Image into the BitmapImage or RenderTargetBitmap Class or Any other class?
This is my Code:
Dim InImage As New BitmapImage(New Uri("My Image Path"))
Dim TG As New TransformGroup
TG.Children.Add(New RotateTransform(190))
Dim MyImg As New Image
MyImg.Source = InImage
MyImg.RenderTransform = TG
'Here i need get Transformed Image into a BitmapImage or RenderTargetBitmap Variable or Any other class variable.
It's a pity that TransformedBitmap does not support rotation with angle other than any multiple of 90 degs (that means we can only rotate 90, 180, 270, ...). Thinking about which objects we can put in a bitmap and apply some Transform? Well we have DrawingGroup, DrawingVisual, ImageBrush, UIElement and via DrawingContext.
Using DrawingGroup, we have to put in an ImageDrawing and apply the transform via the Transform property of the DrawingGroup. Then we have to use a DrawingImage, set the Drawing property to the DrawingGroup.
Using DrawingVisual, we have to open a DrawingContext, use the DrawImage method after pushing some transform. Then we may have to use RenderTargetBitmap by passing the DrawingVisual in the Render method.
Using UIElement (like your idea about using Image control as the medium), we have to render the image on the UIElement. So an Image control suits this best. Every UIElement has a Transform property allowing us to add whatever transform. At last we also have to use a RenderTargetBitmap by passing the UIElement in the Render method.
Using ImageBrush, we have to set the ImageSource property to a BitmapImage. Then we can use the Transform or RelativeTransform property to apply some transform. After that we have to use a DrawingImage. Create a simple GeometryDrawing using the ImageBrush as its Brush, and a RectangleGeometry as its Geometry. Finally we just need to set this GeometryDrawing to the Drawing property of the DrawingImage. The output is the DrawingImage. I would like to use this approach to write the code here:
Dim InImage As New BitmapImage(New Uri("My Image Path"))
Dim ImgBrush As New ImageBrush(InImage)
ImgBrush.Viewport = New Rect(0.1,0.1,0.8,0.8)
ImgBrush.ViewportUnits = BrushMappingMode.RelativeToBoundingBox
Dim Rotating As New RotateTransform(190)
Rotating.CenterX = 0.5
Rotating.CenterY = 0.5
ImgBrush.RelativeTransform = Rotating
Dim ImgSize As New Rect(0,0,300,400)
Dim DrawImage As New DrawingImage()
DrawImage.Drawing = New GeometryDrawing(ImgBrush, null, ImgSize)
Note about the "My Image Path". I've found out that using a Relative image would not work if you don't have any Image folder at the same level with the built exe file. If you don't want to deploy some image folder together with your application, you can add your image as a Resource. To refer to an image added as a Resource in code behind, you have to use a special kind of path:
pack://application:,,,/Your_Relative_Image_Path
Note that to be sure your image is added as a Resource, try right clicking on the image (under the Projects treeview), select Properties in the popup menu, then look into the Build Action field, it should be Resource.
Also note about the ImgBrush.Viewport, setting it appropriately will prevent the image from being cut off (that's because the transformed image is rotated). It depends on the ImgSize and how much degree you rotate.
I want to put an icon on the top left of a radWindow programatically
my code is like this
RadWindow radWindow = new RadWindow();
radWindow.Header = "The header";
radWindow.Icon = new Image()
{
Source = new BitmapImage(new Uri("../ressources/enregistrer.png", UriKind.Relative))
};
radWindow.Show();
but the icon dont show up
does anyone have an idea ?
EDIT
This is the architecture on my project:
The file from where the above code is taken is circled in red
The ressource file is circled in green
<telerik:RadWindow.Icon>
<Image Source="pack://application:,,,/ressources/enregistrer.png" Height="18"/>
</telerik:RadWindow.Icon>
// this seems to work. You will need to provide a size.
I dont know why my solution above did not work but I found a workaround like this
RadWindow radWindow = new RadWindow();
radWindow.Header = "The header";
radWindow.Icon = new Image()
{
Source = new BitmapImage(new Uri("pack://application:,,,/ressources/enregistrer.png", UriKind.RelativeOrAbsolute))
}
radWindow.Show();