I want to bind Image in a listView. Images are saved in Resources Dir and picking will be based on Status parameter which is get from json Array.
I' ve found out that when it is processing, ImageConverter class is not even touched when UI is created. As a result I get listview with empty space for image and filled (as expected) labels.
Question is: How to make it work ?
And
Is there simpler way to perform such operation
XAML FILE:
<ListView x:Name="contentList"
RowHeight="125"
VerticalOptions="FillAndExpand"
SeparatorVisibility="Default"
SeparatorColor="Black"
BackgroundColor="White"
ItemSelected="onOrderSelected"
>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout VerticalOptions="FillAndExpand"
Orientation="Horizontal"
BackgroundColor="White"
>
<Image Source="{Binding Status,Converter={StaticResource ImageConverter }}"
WidthRequest="100"
HeightRequest="100
/>
<StackLayout Orientation="Vertical">
<Label Text="{Binding Title}"
FontSize="Default"
VerticalOptions="Center"
Margin="20,0,0,0"
TextColor="Black"/>
.
.
.
.
</StackLayout>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
CONVERTER:
class ImageConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
string filename = value as string;
return ImageSource.FromStream(() => new MemoryStream(DependencyService.Get<IWRDependencyService>().GetImageBytes(filename)));
}
}
Android Interface Implementation
class ImageLoader : IWRDependencyService
{
public byte[] GetImageBytes(string fileName)
{
fileName = fileName.Replace(".jpg", "").Replace(".png", "");
var resId = Forms.Context.Resources.GetIdentifier(
fileName.ToLower(), "drawable", Forms.Context.PackageName);
var icon = BitmapFactory.DecodeResource(Forms.Context.Resources, resId);
var ms = new MemoryStream();
icon.Compress(Bitmap.CompressFormat.Png, 0, ms);
byte[] bitmapData = ms.ToArray();
return bitmapData;
}
}
As a result I get listview with empty space for image and filled (as expected) labels. Question is: How to make it work ? And Is there simpler way to perform such operation
For Converter to work in Xamarin.Forms, you need to declare the converter in Xaml like below:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:ImageListViewDemo"
x:Class="ImageListViewDemo.MainPage">
<ContentPage.Resources>
<ResourceDictionary>
<local:MyImageConverter x:Key="ImageConverter"/>
</ResourceDictionary>
</ContentPage.Resources>
...
</ContentPage>
Then the converter will be triggered correctly.Here is the basic demo that I made from your codes:ImageListViewDemo.
If your converter is passed the end resulting status value from your JSON you should just need to return the ImageSource according to whatever the status value is since your images are already in the resource directory.
public override object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var status = value as WhateverType;
if (status == someValue1)
{
return ImageSource.FromFile("status1Image.png");
}
else if(status == someValue2)
{
return ImageSource.FromFile("status2Image.png");
}
......
}
Also if it's not going into your converter at all you might want to make sure your Converter is defined either in your App.xaml or the Resources of the Xaml file it's in.
<ListView.Resources>
<ResourceDictionary>
<ImageConverter x:Key="imageConverter" />
</ResourceDictionary>
</ListView.Resources>
Related
what would be the way to bind an element of an 2D multidimensional array in NET MAUI?
I tried to do the following:
<Label Text="{Binding Calendar.MatrixMonth[0,0]}"
Style="{StaticResource subTitleLightTextStyle}"
Grid.Row="2"
HorizontalOptions="Start" />
But that doesn't work, it just shows the error:
No constructor for type 'BindingExtension' has 2 parameters
It seams that you are trying to use the Binding markup extension (which only accepts one parameter as the path of property to bind) You need something like x:Bind in UWP's which unfortunately is not yet supported in MAUI out of the box. But there is a library that allows you to do so here.
So you can try this code (not tested):
<Label Text="{x:Bind Calendar.MatrixMonth[0,0]}"
Style="{StaticResource subTitleLightTextStyle}"
Grid.Row="2"
HorizontalOptions="Start" />
You could use ValueConverter to bind a 2D array as an alternative. Try the following code:
In xaml,
//define a value converter
<ContentPage.Resources>
<local:ArrayToStringConverter x:Key="arrayToStringConverter"/>
</ContentPage.Resources>
...
// for label, consume this converter and pass the parameter "1,1" as index
<Label FontSize="32" HorizontalOptions="Center" Text="{Binding Calendar.MatrixMonth,
Converter={StaticResource arrayToStringConverter},
ConverterParameter='1,1'}">
And you could generate a new file to do value converter:
public class ArrayToStringConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var a = value as string[,];
string p = parameter.ToString();
var index1 = int.Parse(p.Split(",")[0]);
var index2 = int.Parse(p.Split(",")[1]);
return a[index1, index2];
}
....
}
For more info, you could refer to Binding value converters
Hope it works for you.
As of now, i assign the image of a TreeView item using a direct binding to the image's source:
<DataTemplate DataType="{x:Type local:GeoPoint}">
<StackPanel Orientation="Horizontal">
<Image Source="{Binding Color}" Height="32" />
<TextBlock Text="{Binding Name}" VerticalAlignment="Center"/>
</StackPanel>
</DataTemplate>
the Color binding is referring to string containing the path to the PNG, something like "/Resources/red.png"
i would like to make the Color variable of custom type "MarkerColor", an enum containing several colors, and have the image source binding reference this value, so that if
Color = MarkerColor.green; the binding would reference "/Resources/green.png"
Note that the name of the PNG is not necessarily the same as the name of MarkerColor, an "adapter" should be used to convert the type
I know how to do this in Java Android SDK, but not really sure on how to achive this in Wpf
You could create a converter that knows how to convert the enumeration value to a valid resource:
public class ColorResourceConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
MarkerColor color = (MarkerColor)value;
Uri uri;
switch(color)
{
case MarkerColor.Green:
uri = new Uri("Resources/green.png");
break;
case MarkerColor.Red:
uri = new Uri("Resources/red.png");
break;
//...
default:
uri = new Uri("Resources/default.png");
break;
}
return new BitmapImage(uri);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotSupportedException();
}
}
Usage:
<DataTemplate DataType="{x:Type local:GeoPoint}">
<DataTemplate.Resources>
<local:ColorResourceConverter x:Key="ColorResourceConverter" />
</DataTemplate.Resources>
<StackPanel Orientation="Horizontal">
<Image Source="{Binding Color, Converter={StaticResource ColorResourceConverter}}" Height="32" />
<TextBlock Text="{Binding Name}" VerticalAlignment="Center"/>
</StackPanel>
</DataTemplate>
i'm trying to bind a name of a file given by a filepath to a TextBlock. The filepath is stored in a list which is bound to the ItemsSourceProperty of a ListBox. The TextBlock is set as DataTemplate.
My question is: How can i get the name without path and extension and bind it to the TextBlock?
The XAML code for better explanation:
<ListBox Name="MyListBox" Margin="2">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
And the code behind:
string path = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
List<string> PathList = Directory.GetFiles(path, "*.txt").ToList();
Binding myBind = new Binding();
myBind.Source = PathList;
myListBox.SetBinding(ListBox.ItemsSourceProperty, myBind);
One uses a converter to change the text of a selected listbox item which is fully pathed to just the filename.
In the following example there is a list and a textbox next to it. Once an item is selected, the textbox bound to the list's SelectedItem extracts the pathed string which is passed to a converter which returns just the filename to show.
Example
XAML
<Window x:Class="WPFStack.ListBoxQuestions"
xmlns:local="clr-namespace:WPFStack"
xmlns:converters="clr-namespace:WPFStack.Converters"
.../>
<StackPanel Orientation="Horizontal">
<StackPanel.Resources>
<converters:PathToFilenameConverter x:Key="FilenameConverter" />
<x:Array x:Key="FileNames" Type="system:String">
<system:String>C:\Temp\Alpha.txt</system:String>
<system:String>C:\Temp\Beta.txt</system:String>
</x:Array>
</StackPanel.Resources>
<ListBox Name="lbFiles"
ItemsSource="{StaticResource FileNames}" />
<TextBlock Text="{Binding SelectedItem,
ElementName=lbFiles,
Converter={StaticResource FilenameConverter}}"
Margin="6,0,0,0" />
</StackPanel>
Converter
namespace WPFStack.Converters
{
public class PathToFilenameConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
object result = null;
if (value != null)
{
var path = value.ToString();
if (string.IsNullOrWhiteSpace(path) == false)
result = Path.GetFileNameWithoutExtension(path);
}
return result;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return value;
}
}
}
ItemTemplate Use of Converter
The converter is reused in the template as such
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Converter={StaticResource FilenameConverter}}"/>
</DataTemplate>
</ListBox.ItemTemplate>
If you just want to add a static list to list box you should do it like this.
XAML:
<ListBox x:Name="lb" ItemsSource="{Binding Collection}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
The code behind constructor for in the main window:
public MainWindow()
{
InitializeComponent();
List<string> l = new List<string>();
l.Add("string path 1");
l.Add("string path 2");
l.Add("string path 3");
l.Add("string path 4");
lb.ItemsSource = l;
}
You should be aware that there is a much better way of doing these things. I would honestly suggest you go look MVVM and doing a proper binding to a ViewModel.
I am trying to assign an image for each of my pivot items's header instead of a Text .
I tried several methods (one was given by this post http://social.msdn.microsoft.com/Forums/wpapps/en-US/e7b5fd17-3465-4a94-81af-5c056c992c11/add-image-to-pivot-title?forum=wpdevelop )
I managed to assign the same image for my pivot but not one image for each header.
This is what I tried :
<phone:Pivot.HeaderTemplate >
<DataTemplate>
<Image Source="21.jpg" Height="55" Width="55"/>
</DataTemplate>
</phone:Pivot.HeaderTemplate>
This obviously gave me the same image for each headers ,
So i wanted to try something like this :
<phone:Pivot.HeaderTemplate >
<DataTemplate>
<Image Source="{Binding}" Height="55" Width="55"/>
</DataTemplate>
</phone:Pivot.HeaderTemplate>
[...]
<phone:PivotItem ??? >
<// phone:PivotItem >
But then i don't know what to add my image path.
i used this method when i wanted to assign a text as a header and it worked :
<phone:Pivot.HeaderTemplate >
<DataTemplate>
<TextBlock Text="{Binding }" FontSize="88" />
</DataTemplate>
</phone:Pivot.HeaderTemplate>
<phone:PivotItem Header = "Title1" />
How can i assign an image for each of my Header ?
You should be able to simply provide the image source in the Header:
<phone:PivotItem Header = "21.jpg" />
This sets the data context to use for the HeaderTemplate for that particular item.
You need to use a Converter Class to solve this issue.
namespace MyImageConvertor
{
public class MyValueConverter : IValueConverter
{
#region IValueConverter Members
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
try
{
var uri = new Uri((string)(value), UriKind.RelativeOrAbsolute);
var img = new BitmapImage(uri);
return img;
}
catch
{
return new BitmapImage();
}
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
var img = value as BitmapImage;
return img.UriSource.AbsoluteUri;
}
#endregion
}
}
Then use the this convertor in your xaml.
<UserControl x:Class="ValueConverter.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
xmlns:this="clr-namespace:MyImageConvertor">
<UserControl.Resources>
<this:MyValueConverter x:Key="ImageConverter"/>
</UserControl.Resources>
<phone:Pivot>
<phone:Pivot.HeaderTemplate>
<DataTemplate>
<Image Source="{Binding ImageUrlProperty, Converter={StaticResource ImageConverter},Mode=TwoWay}"></Image>
</DataTemplate>
</phone:Pivot.HeaderTemplate>
</phone:Pivot>
Make sure you have the full image path in the ImageUrlProperty value like ..\Images\logo.png.
I have been Bind the Image and other record in the Listview but i have problem in binding the record in DataGrid using linq to sql Please tell me how to bind the Image and first name in the DataGrid . I try to bind it but finally the result in my student table is null means no error but it show no record i am sure that i have some binding problem how can i solve it please please tell me and Thanks for reading . Here is My .xml file of wpf please see and correct the errors on this fill
<Window x:Class="UI.ViewStudent"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:UI"
Title="ViewStudent" Height="577" Width="415" xmlns:my="clr-namespace:Microsoft.Windows.Controls;assembly=WPFToolkit">
<Window.Resources >
<local:ImageDataConverter x:Key="ImageData1Converter"/>
</Window.Resources>
<Grid Height="540">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="9*" />
<ColumnDefinition Width="384*" />
</Grid.ColumnDefinitions>
<my:DataGrid ItemsSource="{Binding }" AutoGenerateColumns="False" Grid.Column="1" Margin="32,0,53,0" Name="dataGrid1" Height="200" VerticalAlignment="Top">
<my:DataGrid.Columns>
<my:DataGridTemplateColumn Header="FirstName">
<my:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBox Text="{Binding Path=FirstName}"
Margin="-6,0,-6,0"/>
</DataTemplate>
</my:DataGridTemplateColumn.CellTemplate>
</my:DataGridTemplateColumn>
<my:DataGridTemplateColumn Header="Imagess">
<my:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Image Height="100" Source="{Binding Path= MyImage, Converter={StaticResource ImageData1Converter}}" />
</DataTemplate>
</my:DataGridTemplateColumn.CellTemplate>
</my:DataGridTemplateColumn>
</my:DataGrid.Columns>
</my:DataGrid>
</Grid >
</Window>
And for my .xml.cs file is
namespace UI
{
/// <summary>
/// Interaction logic for Pics.xaml
/// </summary>
public partial class Pics : Window
{
public Pics()
{
InitializeComponent();
}
private DataClasses1DataContext db = new DataClasses1DataContext();
private BindingListCollectionView CustomerView;
private void Window_Loaded(object sender, RoutedEventArgs e)
{
var custsInCA = from c in db.Students
where c.StudentID == 100
orderby c.LastName, c.FirstName
select c;
this.DataContext = custsInCA;
this.CustomerView = ((BindingListCollectionView)(CollectionViewSource.GetDefaultView(this.DataContext)));
}
//public string value { get; set; }
}
public class ImageDataConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
System.Data.Linq.Binary binaryData = value as System.Data.Linq.Binary;
//System.Data.Linq.Binary binaryData = value;// here there is the first error .How convert BinaryData to Object??
if (binaryData == null)
{
return null;
}
byte[] buffer = binaryData.ToArray();
if (buffer.Length == 0)
{
return null;
}
BitmapImage res = new BitmapImage();
res.BeginInit();
res.StreamSource = new System.IO.MemoryStream(buffer);
res.EndInit();
return res;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
My problem is that i bind the record in DataGrid in wrong way due to that i after compiling i show the Grid but having no record no picture please tell me what is wrong in my my app and how to solve fix it please tell me in completer example how to bind the Image and first name using linq to sql wpf
Check there is space after Path=
<Image Height="100" Source="{Binding Path= MyImage,
Converter={StaticResource ImageData1Converter}}" />