In WPF, How to use Image source with Multi:
<Image x:Name="imgLane1" HorizontalAlignment="Left" Height="25" Margin="180,225,0,0" VerticalAlignment="Top" Width="42" Stretch="Fill">
<Image.Source>
<MultiBinding Converter="StaticResource LaneImageConverter}" UpdateSourceTrigger="PropertyChanged">
<Binding Path="Attachments">
<Binding Path="Delivery"/>
</MultiBinding>
</Image.Source>
</Image>`
public class LaneImageConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
string path = "";
int attachments = 0;
string delivery = values[1].ToString();
Int32.TryParse(values[0].ToString(), out attachments);
return System.Windows.Data.Binding.DoNothing;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
I can not update imageSource with MultiBinding also debug to update source
Please help me ?
The converter must return an instance of a class that is derived from ImageSource, e.g. a BitmapImage that is loaded from the path of an image file:
public object Convert(
object[] values, Type targetType, object parameter, CultureInfo culture)
{
string path = "";
// compose path from values
return new BitmapImage(new Uri(path));
}
When the image file is a assembly resource, you would use a Resource File Pack URI:
var uri = string.Format("pack://application:,,,/images/{0}{1}.png", values); // for example
return new BitmapImage(new Uri(uri));
Related
I have an image in my xaml:
<Image Grid.Column="0" Grid.Row="0" Grid.RowSpan="2" Width="30" Height="30"></Image>
The source for the image is like this:
..\Images\MyFolder\1.png
..\Images\MyFolder\2.png
..\Images\MyFolder\3.png
Basically, the name of the .png file is the id of the items.
In my ViewModel I have a field which represents the id, its name is myId.
How do I add this kind of source - with two hardcoded values and one binding value?
Bind the Image source with the id and apply a converter to create the image path.
The xaml will be:
ente<Image Source="{Binding Path=myId, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay, Converter={StaticResource ConvImageSource}}"/>
And add the resouce at the top:
<Window.Resources>
<local:ImageSourceConverter x:Key="ConvImageSource"/>
</Window.Resources>
And the converter can be:
public class ImageSourceConverter : IValueConverter
{
#region IValueConverter Members
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
String myId = System.Convert.ToString(value);
String imagePath = SPECIFY_IMAGE_PATH;
String imageExtn = SPECIFY_IMAGE_Extn;
// Create the image source
String imageSource = String.Concat(imagePath, myId, imageExtn);
return imageSource;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return value;
}
#endregion
}
Hope this will help.
I need to find the way to save images to the IsolatedStorage and show them I the Silverlight (XAML)
Important: Silverlight have to take image “himself”, I cannot set the image from the code behind
I have tried many solutions before.
The very last solution is, to bind byte array and convert them to the Image
XAML
StackPanel Orientation="Horizontal" Margin="0,0,0,20">
<Image Width="110" CacheMode="BitmapCache" Source="{Binding ThumbLocal,Converter={StaticResource imgConverter}}"
Margin="12,0,9,0"/>
<StackPanel Width="311">
Code behind
public byte[] ThumbLocal
{
get;
set;
}
public class ByteImageConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
MemoryStream memStream = new MemoryStream((byte[])value);
memStream.Seek(0, SeekOrigin.Begin);
BitmapImage thumbLocal = new BitmapImage();
thumbLocal.SetSource(memStream);
return thumbLocal;
}
}
Everything work till I save byte[] to the database and tried to retrieve.
By now I can see the only option save image as file to the IsolatedStorage and then retrieve and covert to byte[].
Is this “smart ” solution?
First, create this converter:
public class BinaryToImageSourceConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value != null && value is byte[])
{
var bytes = value as byte[];
var stream = new MemoryStream(bytes);
var image = new BitmapImage();
image.SetSource(stream);
stream.Close();
return image;
}
return null;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
Second, bind to Your byte[] using this converter, i.e. if you are using MVVM:
View:
<Image Source="{Binding IsolatedStorageImage, Converter={StaticResource BinaryToImageSourceConverter}}" x:Name="ScanImage"/>
You can make property in contrlol (prop snippet) type byte[] and read image to byte array from isostorage, then set value of property to it.
If You got more questions, feel free to ask me.
I have a Value Converter running for an incoming string value from the database, to set the appropriate icon for a gender. The value coming in must be either M or F, and either one will display a male or female icon respectively. The Binding is working to some extent, in that the picture appears, but it is only displaying one set of icons for either value.
The value converter code is as follows:
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var gender = (string)value;
Uri uri;
uri = gender == "F" ?
new Uri("../Resources/Icons/female_user.png", UriKind.Relative) :
new Uri("../Resources/Icons/male_user.png", UriKind.Relative);
return uri;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
and the XAML is as follows
<Image Margin="8" Width="35" Height="35"
VerticalAlignment="Top" HorizontalAlignment="Center"
Source="{Binding Gender, Converter={StaticResource genderConverter}}" />
The resource is cited in the usercontrol.resources and all is properly bound I assume. So why does the converter persistently return only one value?
Try this...
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
var gender = (string)value;
Uri uri;
uri = gender == "F" ?
new Uri("../Resources/Icons/female_user.png", UriKind.Relative) :
new Uri("../Resources/Icons/male_user.png", UriKind.Relative);
BitmapImage img_Gender = new BitmapImage(uri);
return img_Gender;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return null;
}
All I needed was a gender.Trim() to get rid of all white spaces.
var gender = value.ToString();
try
{
return gender.Trim() == "F" ? "../Resources/Icons/male_user.png" : "../Resources/Icons/female_user.png";
}
catch (Exception)
{
return "";
}
Thats took care of it all, and it works. Thanks for the answers and "doh!" possibilites though.
<MenuItem Command="local:CommandLibrary.RegisterServiceCommand">
<MenuItem.CommandParameter>
<MultiBinding Converter="{StaticResource TrayWindowViewModelConverterResource}">
<MultiBinding.Bindings>
<Binding ElementName="Me" />
<Binding FallbackValue="Parser" />
</MultiBinding.Bindings>
</MultiBinding>
</MenuItem.CommandParameter>
</MenuItem>
public class TrayWindowViewModelConverter : IMultiValueConverter {
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) {
var viewModel = new Window1ViewModel();
foreach (var obj in values) {
if (obj is Window)
viewModel.Caller = obj as Window;
else if (obj is string)
viewModel.ServiceName = obj.ToString();
}
return viewModel;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) {
throw new NotImplementedException();
}
}
Button cammand is exactly same as MenuItem. when i debug Converter for MenuItem, values parameter contains two object: DependencyProperty.UnsetValue (I'm not aware what's this) and MyContextMenu object.
And also how can i pass SomeType as parameter?
Thanks
MenuItems exist in popups that are outside the main visual tree and so don't have the same name scope as surrounding elements, like your Button. When trying to bind, the ElementName binding can't resolve because the "Me" element is outside the MenuItem's name scope.
I want to convert a System.Windows.Media.Color value to a System.Windows.Media.Brush. The color value is databound to a Rectangle object's Fill property. The Fill property takes a Brush object, so I need an IValueConverter object to perform the conversion.
Is there a built-in converter in WPF or do I need to create my own? How do I go about creating my own if it becomes necessary?
I know I am really late to the party, but you don't need a converter for this.
You could do
<Rectangle>
<Rectangle.Fill>
<SolidColorBrush Color="{Binding YourColorProperty}" />
</Rectangle.Fill>
</Rectangle>
It seems that you have to create your own converter. Here a simple example to start:
public class ColorToSolidColorBrushValueConverter : IValueConverter {
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
if (null == value) {
return null;
}
// For a more sophisticated converter, check also the targetType and react accordingly..
if (value is Color) {
Color color = (Color)value;
return new SolidColorBrush(color);
}
// You can support here more source types if you wish
// For the example I throw an exception
Type type = value.GetType();
throw new InvalidOperationException("Unsupported type ["+type.Name+"]");
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
// If necessary, here you can convert back. Check if which brush it is (if its one),
// get its Color-value and return it.
throw new NotImplementedException();
}
}
To use it, declare it in the resource-section.
<local:ColorToSolidColorBrushValueConverter x:Key="ColorToSolidColorBrush_ValueConverter"/>
And the use it in the binding as a static resource:
Fill="{Binding Path=xyz,Converter={StaticResource ColorToSolidColorBrush_ValueConverter}}"
I have not tested it. Make a comment if its not working.
A Converter is not needed here. You can define a Brush in XAML and use it. It would be better to define the Brush as a Resource so it can be used other places required.
XAML is as below:
<Window.Resources>
<SolidColorBrush Color="{Binding ColorProperty}" x:Key="ColorBrush" />
</Window.Resources>
<Rectangle Width="200" Height="200" Fill="{StaticResource ColorBrush}" />
I wanted to do this HCL's way rather than Jens' way because I have a lot of things bound to the Color, so there's less duplication and boiler-plate .Fill nodes.
However when trying to write it, ReSharper pointed me to the WPF Toolkit's implementation of the ColorToSolidColorBrushConverter. You need to include the following namespace declaration in the main Window/UserControl node:
xmlns:Toolkit="clr-namespace:Microsoft.Windows.Controls.Core.Converters;assembly=WPFToolkit.Extended"
Then a static resource in the Window/UserControl resources:
<Toolkit:ColorToSolidColorBrushConverter x:Key="colorToSolidColorBrushConverter" />
Then you can do it like HCL's answer:
<Rectangle Fill="{Binding Color, Converter={StaticResource colorToSolidColorBrushConverter}}" />
With some more enhancment to HCL answer, I tested it - it works.
public class ColorToSolidColorBrushValueConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value == null)
return null;
if (value is Color)
return new SolidColorBrush((Color)value);
throw new InvalidOperationException("Unsupported type [" + value.GetType().Name + "], ColorToSolidColorBrushValueConverter.Convert()");
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value == null)
return null;
if (value is SolidColorBrush)
return ((SolidColorBrush)value).Color;
throw new InvalidOperationException("Unsupported type [" + value.GetType().Name + "], ColorToSolidColorBrushValueConverter.ConvertBack()");
}
}
Converter:
[ValueConversion(typeof(SolidColorBrush), typeof(Color))]
public class SolidBrushToColorConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (!(value is SolidColorBrush)) return null;
var result = (SolidColorBrush)value;
return result.Color;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
XAML:
//...
<converters:SolidBrushToColorConverter x:Key="SolidToColorConverter" />
//...
<Color>
<Binding Source="{StaticResource YourSolidColorBrush}"
Converter="{StaticResource SolidToColorConverter}">
</Binding>
</Color>
//...
In addition to HCLs answer: If you don't want to care if System.Windows.Media.Color is used or System.Drawing.Color you can use this converter, which accepts both:
public class ColorToSolidColorBrushValueConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
switch (value)
{
case null:
return null;
case System.Windows.Media.Color color:
return new SolidColorBrush(color);
case System.Drawing.Color sdColor:
return new SolidColorBrush(System.Windows.Media.Color.FromArgb(sdColor.A, sdColor.R, sdColor.G, sdColor.B));
}
Type type = value.GetType();
throw new InvalidOperationException("Unsupported type [" + type.Name + "]");
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
Using Pattern matching there's no need for neither null checking and double casting:
public class ColorToSolidBrushValueConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is Color color) return new SolidColorBrush(color);
throw new InvalidOperationException(nameof(color));
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) => new NotImplementedException();
}
Optional implementation for ConvertBack:
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is SolidColorBrush brush)
{
return brush.Color;
}
throw new InvalidOperationException(nameof(brush));
}