I am using MVVM to bind images to my WPF page, but I have a lot of buttons and wihout pics, hard to determine button purpose. The problem is that VS designer does not show me binded images if I use such URI:
xAxis = new BitmapImage(new Uri("/SettingsManager;component/Icons/CameraIcons/X.png",
UriKind.Relative));
But when I use:
xAxis = new BitmapImage(new Uri("../../Icons/CameraIcons/X.png", UriKind.Relative));
Designer correctly displays image.
I make binding via source:
<ToggleButton.Content> <Image Source="{Binding Source={StaticResource
CameraIcons}, Path=XAxis, Mode=OneWay,
UpdateSourceTrigger=PropertyChanged}"></Image> </ToggleButton.Content>
Does someone know why this happening?
In your first example (that doesn't work), it looks like you provide an absolute URI, but declare it as UriKind.Relative.
In your second example (that does work), it looks like you provide a relative URI, and declare it as UriKind.Relative.
I assume that is why the first example work, but the second one doesn't. You could try using UriKind.Absolute instead in the first example.
Related
I have a WPF application, I should set button image depending on current culture. It works fine for strings:
<Label Content="{x:Static res:Resources.Buy}"></Label>
show string depending on culture, but with image:
<Image Source="{x:Static res:Resources.GetItFree}"></Image>
I get an error. Why and how to do correctly?
I have done this before, but using a library: Infralution.Localization.Wpf. It is very simple the way of doing the images resources references:
<Window Language="{UICulture}" x:Class="WpfApp.MainWindow"
...
Icon="{Resx ResxName=WpfApp.MainWindow, Key=Window.Icon}">...</Window>
This is the final image you get (it changes with culture):
Hope this reference could helps, it works for me...
I'm developing an app for Windows Phone 7 that populates a WrapPanel with a list of objects retrieved from an ObservableCollection<Photo>.
<ListBox ItemsSource="{Binding Photo}">
<ListBox.ItemTemplate>
<DataTemplate>
<Image Source="{Binding File}" />
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<toolkit:WrapPanel ItemHeight="150" ItemWidth="150" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
It's working how it's supposed to work (in the means that it's loading all the images), but I'm having some performance issues since WrapPanel : Panel. So it doesn't virtualize any data, loading all the Image objects of the ListBox, even the ones that the user can't see.
This approach is OK when ObservableCollection<Photo>.Count <= 30 but as the Collection gets bigger and bigger things start to get slow.
Since the user can have up to 1000 images, it's simply not going to work this way. Even though I'm binding Thumbnails to display the Image object.
I've tried to use David Anson's LowProfileImageLoader to create Images off the UI thread. And to bind the Images as the user scrolls the ListBox. But it doesn't work since it's expecting an UriSource and I'm actually binding a BitmapImage to the Image.Source, because the images are beeing loaded from IsolatedStorage.
public class Photo : INotifyPropertyChanged, INotifyPropertyChanging
{
...
...
public BitmapImage File
{
get
{
// Thumbnail
string filePath = Path.Combine("Images", FileName);
byte[] data;
using (IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication())
{
using (IsolatedStorageFileStream isfs = isf.OpenFile(filePath, FileMode.Open, FileAccess.Read))
{
data = new byte[isfs.Length];
isfs.Read(data, 0, data.Length);
isfs.Close();
}
}
MemoryStream ms = new MemoryStream(data);
BitmapImage bi = new BitmapImage();
bi.SetSource(ms);
return bi;
}
}
}
Can anyone help me in this task of making the content (photos) load as the user sees it? Is there anything such as a VirtualizingWrapPanel or WrapPanel : VirtualizingPanel?
Thanks. If any code snippet is needed feel free to ask.
Loading the images to memory from the storage when the user scrolls will make your UI jittery especially when the user tries to scroll or see more elements very quickly.
But, if you have all the images in memory and then would like to bind the images to the listbox on scrolling, you could use the VirtualizingStackPanel. A wrap panel would need to know the size of the images to display correctly. A workaround is possible if you know the size of the images and if they're all the same.
You could customize the VirtualizingStackPanel and position the images in rows like the way they would in a wrappanel, or any other way you like.
Hope that helps.
Although,
I am not sure if this will solve the problem when you have 1000 heavy images. But it is worth a try, if you haven't done so.
EDIT: This article might help.
Try creating a wrap panel from a virtualized listbox.
Here is a link how to do it. it works pretty good, but it has 1 problem... it will have a tilt effect on a whole line instead of an item... I'm currently investigating that problem.
I used to be able to do so very much with just the Bitmap and Graphics objects. Now that I've been using WPF the only thing I seem to be able to do is load an image and show it and make it dance around the stupid screen. Why did they get rid of these very useful tools. Are they trying to stupefy .Net?
All I want to do is load an image from a file and cut it into two parts. This was easy with .Net 2.0 and System.Drawing. But with WPF, I'm hitting a brick wall without using some very low level code. I've tried working with WriteableBitmap. But it doesn't seem to really be what I'm wanting. Is there no way to wrap a DrawingContext around a BitmapImage or something?
Please tell me that WPF is more than HTML for applications. I am REALLY frustrated!!
Edits:
Also, how on earth does one save an image to a file?
If you want to cut the image in two parts, why not use the CroppedBitmap class?
Consider the following XAML. One source BitmapImage shared by two CroppedBitmaps, each showing different parts of the source.
<Window.Resources>
<BitmapImage x:Key="bmp" UriSource="SomeBitmap.jpg" />
</Window.Resources>
<StackPanel>
<Image>
<Image.Source>
<CroppedBitmap Source="{StaticResource ResourceKey=bmp}">
<CroppedBitmap.SourceRect>
<Int32Rect X="0" Y="0" Width="100" Height="100" />
</CroppedBitmap.SourceRect>
</CroppedBitmap>
</Image.Source>
</Image>
<Image>
<Image.Source>
<CroppedBitmap Source="{StaticResource ResourceKey=bmp}">
<CroppedBitmap.SourceRect>
<Int32Rect X="100" Y="150" Width="50" Height="50" />
</CroppedBitmap.SourceRect>
</CroppedBitmap>
</Image.Source>
</Image>
</StackPanel>
Update: to do something similar in code:
var bitmapImage = new BitmapImage(new Uri(...));
var sourceRect = new Int32Rect(10, 10, 50, 50);
var croppedBitmap = new CroppedBitmap(bitmapImage, sourceRect);
Well there is this http://www.nerdparadise.com/tech/csharp/wpfimageediting/
or perhaps you could add a reference to System.Drawing to your project and then do the editing the way you are comfortable with.
You are probably best off using TransformedBitmap. Load your Bitmap as a BitmapSource, then set the Transform property to however you want the image to transform. You have several different transformation options here. This allows you to rotate, screw, matrix, etc. transformations. If you want to apply more than one, use a TransformGroup and apply several transformations at once.
You can also use BitmapFrame.Create(...) to work with the transformed image more.
Some Pseudo code:
var image = new BitmapSource(...); //Your image
var transformBitmap = new TransformedBitmap(image);
var transformBitmap.Transform = ..//Set your transform;
//optionally:
var frame = BitmapFrame.Create(transformBitmap);
I am having difficulty trying to get a very simple scenario working with PRISM 2.0 for WPF. I want the main workarea of my application to be a TabControl. Each time I add a view, I want it to appear as a TabItem on the TabControl.
Sounds easy right?
My region, which is in my Shell.XAML looks like this:
<Controls:TabControl
Name="MainRegion"
cal:RegionManager.RegionName="{x:Static Infrastructure:RegionNames.TabRegion}"
ItemContainerStyle="{StaticResource ShellTabItemStyle}" />
The style: ShellTabItemStyle looks like this:
<Style x:Key="ShellTabItemStyle" TargetType="{x:Type TabItem}">
<Setter Property="Header" Value="{Binding Content.DataContext.HeaderInfo, RelativeSource={RelativeSource Self}}" />
</Style>
This should set the Header of the TabItem to the HeaderInfo property on the DataContext of the view. (I got this idea from this article) The DataContext of my view is a very simple Presenter which has a HeaderInfo property on it:
public string HeaderInfo = "The Header Text";
My view is a simple WPF usercontrol and looks like this:
<StackPanel>
<TextBox Text="Hello World" Name="MyTextBox"></TextBox>
<Image Source="..SomeImage.PNG" Name="MyImage"></Image>
</StackPanel>
So far, so good. If I add the view to the region I get a tab control and I get a tab with the text set to "The Header Text". My problem is that there is absolutely no content appearing on the tab. My view contains a simple Image and a TextBox, but neither of them show up in the TabItem. If I break out Snoop and look around, there isn't an image in sight.
What am I missing here - is there an easier way?
I was unable to get any of the suggested answers to work. Extensive googling didn't help either. I gave the problem some thought over the weekend and more I thought about it, the more it occured to me that there is a bit of a code smell about this approach. You inject a view into your Tab Region... some magic stuff happens and a tab gets added... you have to add some imcomprehensible dynamic binding to some XAML styling stored in a file somewhere and this may or may not set your header text. If any one single element of this is just a little bit wrong you won't get an error but it just won't work.
In my view this is both brittle (i.e. very easy to break) and pretty inpenetrable unless you have a deep understanding PRISM, the model, and of XAML. Fortunately there is a much nicer and simpler way to do this:
Simply create a view called TabRegionView which contains only a blank TabControl. You probably want to add this to your Shell.xaml. Create an Event called InjectTabView which has a Payload of type UserControl and subscribe to this event in your TabRegionView control. When the event fires in TabRegionView, you create the TabItem manually and add the view to the TabItem like so:
public void TabAdded(UserControl view)
{
var item = new TabItem();
item.Content = view;
item.IsSelected = true;
item.Header = "Header Text";
mainTab.Items.Add(item);
}
When you want to display a view as a new tab, your code looks something like this:
var view = new View(params);
_eventAggregator.GetEvent<InjectTabViewEvent>()
.Publish(view);
This will be picked up by TabRegionView and the view will be added as a new tab. You could easily wrap the View in harness of some type that contains header text, an image and bool to indicate whether or not the tab should be autoselected.
IMHO this technique has the dual advantages of giving you direct control of what is going on AND it is much easier to follow.
I'd be very interested to get an opinion on this from any PRISM officianados.
If you are using RegionManager, you need to Activate your view. There's likely some piece of code where you are adding the view to the region, you just additionally need to tell that region to activate it.
public void AddViewToRegion(IRegion region, object view)
{
region.Add(view);
region.Activate(view);
}
It seems silly, but you get the behavior you are seeing if you don't do this. I found this kinda frustrating, but it was easy enough to fix. The behavior is even stranger when you add multiple tabs if you don't at least Activate the first view you add.
My understanding is that if you don't do this, the view never becomes part of the visual tree (this is a side-effect of the fact that the TabControl deactivates (removes from the visual tree) when a tab isn't "in front". This is good for certain operations, but makes things like this be a little wonky.
Some random thoughts:
try to remove the style from TabControl
check visual tree with help of Snoop tool. You should see your TabItem with view's UserControl under the TabControl. Next you can check what's wrong with that UserControl and its children (your view's content). They are probably hidden for some reason.
other thing to think over - RegionAdapter. RegionAdapters are responsible for adapting regions' views to host UIControl.
I'm building a Silverlight 2 application and I need to bind some images to Image object declarated in XAML. I'm doing some other binding in the application and it works just fine, I'm having problem with only images!
This is it's XAML:
<Image Source="{Binding Path=ThumbNail}" Style="{StaticResource ThumbNailPreview}" />
And this is the C# code-behind:
ThumbNail = (string)story.Element("thumbnail").Attribute("src")
I'm just parsing the URL's from a XAML file. When I try to do a foreach loop over all of the ThumbNail properties, it returns the URL as expected. As I said, all other binding works great, so it has to be a problem between the Image control and the ThumbNail property. I also tried chanding the datatype from string to Uri, but nothing happened. Could anyone help me?
I think this has already been asked and answered in StackOverflow here
The key is that the ImageSource property is not a string but a System.Windows.Media.Imaging.BitmapImage type and so needs to be converted.
HTH