Windows Phone Display image - windows-phone-7

All My data photo is in server Example url: http://abcd.com/images/ and i have renamed all the photos file to my album id example 1.jpg,2.jpg
and i want to display those photos using albumid in grid view
class AlbumData
{
public Int32 AlbumId { get; set; }
public String Name { get; set; }
public String Language { get; set; }
public String Actors { get; set; }
public String Director { get; set; }
public String MusicDirector { get; set; }
public String Year { get; set; }
}
private void Search_Click(object sender, RoutedEventArgs e)
{
WebClient webclient = new WebClient();
webclient.DownloadStringCompleted += new DownloadStringCompletedEventHandler(webclient_DownloadStringCompleted);
webclient.DownloadStringAsync(new Uri("http://albums.abcd.com/v1/Albums/English/1"));//--getting data using xml
}
void webclient_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
if (e.Error != null)
{
MessageBox.Show("error");
}
XElement XmlTweet = XElement.Parse(e.Result);
listBox1.ItemsSource = from tweet in XmlTweet.Descendants("Album")
select new AlbumData()
{
Name = tweet.Element("Name").Value,
//--how to display image---//
};
}
Please help me with example
<DataTemplate>
<StackPanel>
<Image Source="{Binding ImageSource}" Height="100" Width="100" HorizontalAlignment="Center" VerticalAlignment="Center" />
<TextBlock Text="{Binding Name}" Foreground="#FFC8AB14" FontSize="15" Width="120" TextAlignment="Center" TextWrapping="Wrap" />
<!--<TextBlock Text="{Binding Message}" TextWrapping="Wrap" FontSize="8" Width="100" TextAlignment="Center" />-->
<!--<TextBlock Text="{Binding MusicDirector}" TextWrapping="Wrap" FontSize="8" Width="100" TextAlignment="Center" />-->
<!--<TextBlock Text="{Binding UserName}" Style="{StaticResource PhoneTextSubtleStyle}" Width="100" TextAlignment="Center"/>-->
</StackPanel>
</DataTemplate>

Assuming the ElementName of your images is ImageUri, you must change your ItemsSource to:
listBox1.ItemsSource =
from tweet in XmlTweet.Descendants("Album")
select new AlbumData()
{
Name = tweet.Element("Name").Value,
ImageSource = new BitmapImage(new Uri(tweet.Element("ImageUri"), UriKind.Relative));
};
AlbumData needs to be extended by
public BitmapImage ImageSource { get; set; }

Related

Xamarin Forms How can I use ListView for show string[] which is part of the same JSON response that show inside a CarouselView?

All the fields show ok, only Specilities string[] shows me an error... remember there are two different fids on json response we have Speciality that is OK and show OK... and we have Specilities string[] where is the problem.... check the json response
this is json response
{"_id":"5aab4c02f08d9324fc1283ec","firstName":"Carlos Alberto","lastName":"Cabezas Delgado","password":"$2a$10$BuYWhiMn.9RsBKJN7bWuguKaPAHQocd2eVQCqRaaAdmzrlPkuWYJS","identificationNumber":"0914891684","email":"carlos.cabezas#abogadosecuador.com.ec","phone":"0969922421","discount":0.5,"band":3,"city":"59cda262fe728437ce90ff81","role":"59cd270f07308946e6a494f7","__v":6,
"speciality":{"_id":"5a0a6176257e970afc9a9e7f","name":"Propiedad Intelectual","tag":"propiedad-intelectual","__v":0,"icon":"speciality_icon_jg4zpoeqoiwtuuy8jya.png","description":"Derechos de propiedad industrial, derechos de autor, patentes, modelos de utilidad, diseños industriales, marcas, indicaciones geográficas, información comercial confidencial, derecho de obtentor.","id":"5a0a6176257e970afc9a9e7f"},
"profile":"5aac7b42c02ece25becefd47","telephone":"593969922421","createdAt":"2018-08-20T03:07:03.838Z","searchTag":"CARLOSALBERTOCABEZASDELGADO","updatedAt":"2020-06-22T00:17:30.971Z","label":"CARLOS ALBERTO CABEZAS DELGADO","firstNameLabel":"Carlos Alberto","lastNameLabel":"Cabezas Delgado","plan":"5d75e792184bab2c72b3d3ab","seller":"5ad72ce8fd69e7aba867c118","telephone2":"","fax":"593969922421","isPublic":true,"isDelete":false,
"invoices":[],
"specialities":["5990d7273da48f4bd98c6918","5990d73f3da48f4bd98c691a","5a0a6055257e970afc9a9e70","5a0a6087257e970afc9a9e73","5a0a6120257e970afc9a9e7a","5a0a6166257e970afc9a9e7e","5a0a6176257e970afc9a9e7f"],
"location":{"address":"Urbanización Puerto Azul, Guayaquil, Ecuador","reference":"Puerto Azul, Vía la Costa (Edificio Torres del Edén)","latitude":-2.1902934315119,"longitude":-79.9647494058045},"status":2,"id":"5aab4c02f08d9324fc1283ec","search":"CARLOS ALBERTO CABEZAS DELGADO"
MODEL DATA
namespace App1
{
public class AbogadosMongoApi
{
[JsonProperty("_id")]
public string Idab { get; set; }
[JsonProperty("label")]
public string FirtsName { get; set; }
[JsonProperty("email")]
public string Correo { get; set; }
[JsonProperty("phone")]
public string Celular { get; set; }
[JsonProperty("password")]
public string Contrasena { get; set; }
[JsonProperty("isPublic")]
public bool Public { get; set; }
[JsonProperty("band")]
public int Band { get; set; }
[JsonProperty("plan")]
public string Plan { get; set; }
[JsonProperty("city")]
public string Ciudadperfil { get; set; }
[JsonProperty("location")]
public Location location { get; set; }
[JsonProperty("speciality")]
public Speciality speciality { get; set; }
[JsonProperty("specialities")]
public string[] Specialities { get; set; }
}
public class Speciality
{
[JsonProperty("_id")]
public string Idespecialidad { get; set; }
[JsonProperty("name")]
public string Nombrespecialidad { get; set; }
[JsonProperty("icon")]
public string Iconespecialidad { get; set; }
[JsonProperty("description")]
public string Descespecialidad { get; set; }
}
public class Location
{
[JsonProperty("address")]
public string Direccion { get; set; }
[JsonProperty("reference")]
public string Referencia { get; set; }
[JsonProperty("latitude")]
public string Latitud { get; set; }
[JsonProperty("longitude")]
public string Longitud { get; set; }
}
}
XAML
<CollectionView x:Name="abogadosrec"
BackgroundColor="#eee"
SelectionMode="Single"
SelectionChanged="CallBtnClicked"
VerticalOptions="StartAndExpand"
HorizontalOptions="CenterAndExpand">
<CollectionView.ItemTemplate>
<DataTemplate>
<SwipeView>
<SwipeView.LeftItems>
<SwipeItems>
</SwipeItems>
</SwipeView.LeftItems>
<SwipeView.RightItems>
<SwipeItems>
<SwipeItem Text="Crear Cita"
BackgroundColor="#00a783" />
</SwipeItems>
</SwipeView.RightItems>
<Grid Style="{StaticResource IndicatorLabelStyle}"
Padding="20">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Frame CornerRadius="100"
HeightRequest="75"
WidthRequest="75"
BorderColor="#cca876"
HorizontalOptions="Center"
Padding="0"
IsClippedToBounds="True">
<Image xct:TouchEffect.PressedScale="1.4"
Grid.RowSpan="2"
Source="{Binding Idab, StringFormat='https://abogadosecuador.com.ec/profile/picture/{0:N}'}"
Aspect="AspectFill"
HeightRequest="75"
WidthRequest="75" />
</Frame>
<Label Grid.Column="1"
Text="{Binding FirtsName}"
VerticalOptions="CenterAndExpand"
HorizontalOptions="StartAndExpand"
FontSize="Micro"
FontAttributes="Bold" />
<ListView ItemsSource="{Binding .}"
HasUnevenRows="true">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Label FontSize="3" Text="{Binding Specialities}"></Label>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<Label Grid.Column="1"
x:Name="txtNumero" IsVisible="false"
Text="{Binding Celular, Mode=TwoWay}"
FontAttributes="Italic"
VerticalOptions="CenterAndExpand"
HorizontalOptions="StartAndExpand" />
</Grid>
</SwipeView>
</DataTemplate>
</CollectionView.ItemTemplate>
<CollectionView.Header>
<StackLayout BackgroundColor="LightGray">
<Label Margin="10,0,0,0"
Padding="10"
Text="Abogados Registrados"
FontSize="Small" />
</StackLayout>
</CollectionView.Header>
</CollectionView>
this
<ListView ItemsSource="{Binding .}"
should be
<ListView ItemsSource="{Binding Specialities}"
and this
<Label FontSize="3" Text="{Binding Specialities}" />
should be
<Label FontSize="3" Text="{Binding .}" />

Images saved in database are not displaying in the Home.xaml page in Xamarin Forms app

In my Xamarin Forms app Home.xaml are not displaying the image back after saving in database. While debugging I could see, bytes[] are displaying at PlayerImage against the player. In the xaml, I have Source="{Binding PlayerImage}" but couldn't figure the reason for not displaying. Are the bytes displaying correct at the break point ?
// Home.xaml
<ContentPage.Resources>
<DataTemplate x:Key="playerTemplate">
<ContentView>
<StackLayout Margin="5,5" BackgroundColor="#584961">
<Image x:Name="{PlayerImage}" Source="{Binding PlayerImage}" WidthRequest="25" HeightRequest="25"/>
<Label Text="{Binding FullName}" Font="Bold,18" TextColor="White"/>
<Label Text="{Binding Mobile}" Font="Bold,13" TextColor="White"/>
<Label Text="{Binding SoccerPosition}" Font="Bold,13" TextColor="White"/>
<Button Text="Remove Player" Clicked="DeleteButton_OnClicked" WidthRequest="120" HeightRequest="50" TextColor="White" BackgroundColor="#d6b947"></Button>
</StackLayout>
</ContentView>
</DataTemplate>
</ContentPage.Resources>
<StackLayout Margin="5">
<CollectionView x:Name="collectionview"
ItemTemplate="{StaticResource playerTemplate}">
<!--span here decides the number of items shows in one line. Now is 3 items one line-->
<CollectionView.ItemsLayout>
<GridItemsLayout Orientation="Vertical" Span="3" />
</CollectionView.ItemsLayout>
</CollectionView>
</StackLayout>
// PlayerDetails.cs
public byte[] PlayerImage { get; set; }
//Home.xaml.cs
public void DisplayDetails()
{
List<PlayerDetails> details = (from x in conn.Table<PlayerDetails>() select x).ToList();
for (int i = 0; i < details.Count; i++)
{
players.Add(details[i]);
}
}
// Added my PlayerDetails.cs class also
public class PlayerDetails : INotifyPropertyChanged
{
[PrimaryKey, AutoIncrement]
public int id { get; set; }
public string Password { get; set; }
public string ConfirmPassword { get; set; }
public byte[] PlayerImage { get; set; }
string fullname;
string mobile;
string soccerposition;
string email;
public PlayerDetails()
{
}
[Ignore]
public Image Image
{
get
{
var image = new Image();
image.Source = ImageSource.FromStream(() => new MemoryStream(PlayerImage));
return image;
}
set
{
//PlayerImage = Convert.ToByteArray(value.Source);
//Bitmap.FromStream(inStream);
}
}
public string FullName
{
set
{
if (fullname != value)
{
fullname = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("FullName"));
}
}
}
get
{
return fullname;
}
}
public string Mobile
{
set
{
if (mobile != value)
{
mobile = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("Mobile"));
}
}
}
get
{
return mobile;
}
}
public string SoccerPosition
{
set
{
if (soccerposition != value)
{
soccerposition = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("SoccerPosition"));
}
}
}
get
{
return soccerposition;
}
}
public string Email
{
set
{
if (email != value)
{
email = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("Email"));
}
}
}
get
{
return email;
}
}
//public ImageSource Source { get; internal set; }
public event PropertyChangedEventHandler PropertyChanged;
}
If you load an Image from a byte[] array in the Xamarin.Forms, you can try the following code:
c# code:
byte[] bitmapData = ...;
ImageSource imageSource= ImageSource.FromStream(() => new MemoryStream(bitmapData));
PlayerImage.Source = imageSource;//binding in code
The xaml code:
<Image x:Name="PlayerImage" WidthRequest="25" HeightRequest="25"/>
Or binding in xaml
<image Source="{Binding imageSource}"/>
Note:
I found the x:Name="{PlayerImage}" is not correct.
It's should be: x:Name="PlayerImage" not x:Name="{PlayerImage}"
you only need to use one way of the following binding methods:
PlayerImage.Source = imageSource;// in code
And
<Image x:Name="PlayerImage" Source="{Binding imageSource}" />
Update:
You can try to make use of a Converter derived from IValueConverter which could create the image back based on the byte array.
ByteArrayToImageSourceConverter.cs
public class ByteArrayToImageSourceConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
ImageSource retSource = null;
if (value != null)
{
byte[] imageAsBytes = (byte[])value;
var stream = new MemoryStream(imageAsBytes);
retSource = ImageSource.FromStream(() => stream);
}
return retSource;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
PlayerDetails.cs
public class PlayerDetails
{
// other fields
public byte[] PlayerImage { get; set; }
}
xaml(a usage example):
<ContentPage.Resources>
<ResourceDictionary>
<myformapp1:ByteArrayToImageSourceConverter x:Key="ByteArrayToImage"
/>
</ResourceDictionary>
</ContentPage.Resources>
<StackLayout Margin="5">
<CollectionView x:Name="collectionView"
ItemsSource="{Binding YoudataList}"> <!--changd to your dataList-->
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid Padding="10">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Image Grid.RowSpan="2"
x:Name="PlayerPic"
Source="{Binding PlayerImage, Converter={StaticResource ByteArrayToImage}}"
Aspect="AspectFill"
HeightRequest="60"
WidthRequest="60" />
<Label Grid.Column="1"
Text="test1"
FontAttributes="Bold" />
<Label Grid.Row="1"
Grid.Column="1"
Text="test2"
FontAttributes="Italic"
VerticalOptions="End" />
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</StackLayout>

How can I bind a row so I can set isVisible to false in .cs file?

It seems that I can't access it even if I put a name on it because it's inside a listview. If i wan row1 to not be visible on code behind how do i go around this?
I tried to a name for Label but I can't access it. or added I cant access on code behind.
<ListView x:Name="postListView" SeparatorVisibility="Default" HasUnevenRows="True" ItemsSource="{Binding Items}" SeparatorColor="White">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid BackgroundColor="Black" HorizontalOptions="CenterAndExpand"
VerticalOptions="FillAndExpand" Padding="1,2,1,0">
<Grid HorizontalOptions="CenterAndExpand"
VerticalOptions="FillAndExpand" ColumnSpacing="1" RowSpacing="1">
<Grid.RowDefinitions >
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="120"/>
<ColumnDefinition Width="100"/>
</Grid.ColumnDefinitions>
<Label Grid.Row="0" FontSize="Medium" Grid.Column="0" Text="right tst:" HorizontalTextAlignment="Start" BackgroundColor="cornflowerblue" />
<Label Grid.Column="1" Grid.Row="0" Text="{Binding drain1vol}" HorizontalTextAlignment="Center" BackgroundColor="cornflowerblue"/>
<Label Grid.Row="1" Grid.Column="0" Text="nothing" BackgroundColor="Yellow"/>
<Label Grid.Row="1" Grid.Column="1" Text="{Binding drain2vol}" HorizontalTextAlignment="Center" BackgroundColor="Yellow" />
</Grid>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
//Model and Source of data
using System;
using SQLite;
using Demo.Helpers;
namespace Demo.Model
{
//this is the source of Binding
public class Post
{
//ID primary key that we will autoincrement
//These are binding source for Historypage
[PrimaryKey, AutoIncrement]
public int ID { get; set; }
public bool showLabel { get; set; } //public class model
}
}
The source is the Post class.
Binding the label's IsVisible property to the property in your model to control the visiable ability of the label.
For example,
In xaml:
<Label Grid.Column="1" Grid.Row="0" IsVisible="{Binding showLabel}" Text="{Binding drain1vol}" HorizontalTextAlignment="Center" BackgroundColor="cornflowerblue"/>
And then in your model:
public class model
{
public string drain1vol { get; set; }
public bool showLabel { get; set; }
}
When you create the dataSource, you can set the label's isVisable:
Items.Add(new model { drain1vol = "Rob Finnerty" ,showLabel= false });
Items.Add(new model { drain1vol = "Bill Wrestler", showLabel = true });
Items.Add(new model { drain1vol = "Dr. Geri-Beth Hooper", showLabel = false });
Items.Add(new model { drain1vol = "Dr. Keith Joyce-Purdy", showLabel = true });
Items.Add(new model { drain1vol = "Sheri Spruce", showLabel = false });
postListView.ItemsSource = Items;
To change the visiable ability in code behind:
void test() {
//Get the model you want to change
model.showLabel = false / true;
}
Update:
Implement the INotifyPropertyChanged interface in your model:
class model : INotifyPropertyChanged
{
private bool showLabel { get; set; }
private string drain1vol { get; set; }
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public event PropertyChangedEventHandler PropertyChanged;
public bool ShowLabel
{
set
{
if (showLabel != value)
{
showLabel = value;
OnPropertyChanged("ShowLabel");
}
}
get
{
return showLabel;
}
}
public string Drain1vol
{
set
{
if (drain1vol != value)
{
drain1vol = value;
OnPropertyChanged("Drain1vol");
}
}
get
{
return drain1vol;
}
}
}
And in your xaml, binding to ShowLabel and Drain1vol(upper-case):
<Label Grid.Column="1" Grid.Row="0" IsVisible="{Binding ShowLabel}" Text="{Binding Drain1vol}" HorizontalTextAlignment="Center" BackgroundColor="cornflowerblue"/>

Find the index of the List items - WP7

I have listbox which contains buttons listed vertically with related datas as given below;
<ListBox Name="CTransactionList" Margin="0,0,0,0" >
<ListBox.ItemTemplate >
<DataTemplate>
<Button Width="400" Height="200" Background="#6A040B2E" Click="completetransact">
<Button.Content >
<StackPanel Orientation="Horizontal" Height="200" Width="400">
<Image Source="{Binding Type1}" Width="80" Height="80" VerticalAlignment="Top" Margin="0,40,0,0"/>
<StackPanel Orientation="Vertical" Height="200">
<StackPanel Orientation="Horizontal" Height="30">
<TextBlock Width="100" FontSize="22" Text="Name:" Height="30"/>
<TextBlock Width="200" FontSize="22" Text="{Binding Date1}" Height="30"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Height="30">
<TextBlock Width="100" FontSize="22" Text="Difficulty:" Height="30"/>
<TextBlock Width="200" FontSize="22" Text="{Binding Amount1}" Height="30"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Height="30">
<TextBlock Width="110" FontSize="22" Text="TotalTime:" Height="30"/>
<TextBlock Width="200" FontSize="22" Text="{Binding Time1}" Height="30"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Height="30">
<TextBlock Width="100" FontSize="22" Text="Distance:" Height="30"/>
<TextBlock Width="200" FontSize="22" Text="{Binding Dis1}" Height="30"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Height="65">
<TextBlock Width="290" FontSize="14" Text="{Binding Def1}" Height="65" TextWrapping="Wrap" FontStyle="Italic"/>
</StackPanel>
</StackPanel>
</StackPanel>
</Button.Content>
</Button>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
And I'm binding the data with such classes;
[DataContract]
public class CTransaction
{
[DataMember]
public String Date1 { get; set; }
[DataMember]
public String Amount1 { get; set; }
[DataMember]
public String Type1 { get; set; }
[DataMember]
public String Time1 { get; set; }
[DataMember]
public String Dis1 { get; set; }
[DataMember]
public String Def1 { get; set; }
[DataMember]
public String Cdate1 { get; set; }
[DataMember]
public String Strpt1 { get; set; }
[DataMember]
public String Endpt1 { get; set; }
[DataMember]
public int Index1 { get; set; }
public CTransaction(String date1, String amount1, String type1, String time1, String dis1, String def1, String cdate1, String strpt1, String endpt1,int index1)
{
this.Date1 = date1;
this.Amount1 = amount1;
this.Time1 = time1;
this.Dis1 = dis1;
this.Def1 = def1;
this.Cdate1 = cdate1;
this.Strpt1 = strpt1;
this.Endpt1 = endpt1;
this.Index1 = index1;
switch (type1)
{
case "FR":
this.Type1 = "Images/a.png";
break;
case "TA":
this.Type1 = "Images/b.png";
break;
case "DA":
this.Type1 = "Images/c.png";
break;
case "CC":
this.Type1 = "Images/mount.png";
break;
}
}
}
As shown above, I have a data binding named Index1 which indexes the button with an arbitrary integer. I want to remove a specified indexed button by user with this code;
ctransactionList.RemoveAt("index comes here");
My exact desire is to remove the clicked button,(i.e. if the second button clicked, then remove the second one). And I tried to embed some indexes(i.e. Index1) in it to remove it, I couldn't find any possible way; I also failed again.
This is the way I tried;
The removal code given above only removes the indexed item based on the whole list item count. I mean, for example, the first element always has the '0' index. It does not care my Index1 data.(I can retrieve the Index1 data with selectedButton as sender method) I wish I could have removed the button which includes the user-specified Index1 data.
How can I do this?
Thanks in advance.
(Windows Phone 7)
You can do this by adding click event handler for button:
private void Button_Click(object sender, RoutedEventArgs e)
{
var button = sender as Button;
var item = button.DataContext as CTransaction;
if (item != null)
{
ctransactionList.Remove(item);
}
}
ctransactionList should be an ObservableCollection.

How to use ValidatesOnDataErrors on a TextBox inside an ItemsControl

I'm trying to have a TextBox's content be validated using IDataErrorInfo. The source of the list below is a List and each item is display. When i put ValidatesOnDataErrors=True in the Binding for the Text on the TextBox, it's not working as expected. How do I do this?
<ItemsControl ItemsSource="{Binding Trainings}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel>
<StackPanel>
<TextBlock Text="{Binding MobileOperator}" />
<TextBlock Text="{Binding LastUpdate}"/>
</StackPanel>
<StackPanel>
<TextBlock Text="Number trained*" />
<!-- ValidatesOnDataErrors doesn't work here-->
<TextBox
Text="{Binding NumberTrained,
ValidatesOnDataErrors=True}"/>
</StackPanel>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Update: Posting a stripped down version of Model, ViewModel, View and CodeBehind
ViewModel and Model
public class MyViewModel : IDataErrorInfo, INotifyPropertyChanged
{
public MyViewModel()
{
Trainings = new List<MyModel>
{
new MyModel { NumberTrained = 5, MobileOperator = "MO 1", LastUpdate = DateTime.Now },
new MyModel { NumberTrained = 1, MobileOperator = "MO 2", LastUpdate = DateTime.Now },
};
OkButtonCommand = new ButtonCommand(OnClick);
}
private void OnClick()
{
PropertyChanged(this, new PropertyChangedEventArgs(""));
}
public event PropertyChangedEventHandler PropertyChanged;
public ICommand OkButtonCommand { get; private set; }
public List<MyModel> Trainings { get; private set; }
public string Error { get { return null; } }
public string this[string columnName]
{
get
{
string error = null;
switch (columnName)
{
case "NumberTrained":
error = "error from IDataErrorInfo";
break;
}
return error;
}
}
}
public class MyModel
{
public string MobileOperator { get; set; }
public DateTime LastUpdate { get; set; }
public int NumberTrained { get; set; }
}
public class ButtonCommand : ICommand
{
private Action _handler;
public event EventHandler CanExecuteChanged;
public ButtonCommand(Action handler) { _handler = handler; }
public bool CanExecute(object parameter) { return true; }
public void Execute(object parameter) { _handler(); }
}
Code Behind
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
DataContext = new MyViewModel();
}
}
View
<Canvas x:Name="LayoutRoot" Background="White">
<ItemsControl ItemsSource="{Binding Trainings}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel HorizontalAlignment="Center">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<TextBlock Text="{Binding MobileOperator}" Margin="15,15,0,0" FontWeight="Bold"/>
<TextBlock Text="{Binding LastUpdate, StringFormat=' - Last Updated: \{0:M/d/yy\}'}"
Margin="5,15,15,0" Foreground="Gray"/>
</StackPanel>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<TextBlock Text="Number trained*" />
<TextBox Width="50" Height="20"
Text="{Binding NumberTrained, Mode=TwoWay, ValidatesOnExceptions=True, ValidatesOnDataErrors=True}"/>
</StackPanel>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<Button Content="ok" Width="100" Height="20" Canvas.Left="248" Canvas.Top="207" Command="{Binding OkButtonCommand}"/>
</Canvas>
I feel implementing IDataErrorInfo on ViewModel is more appropriate rather than on Model.
So in your case, you could have created an additional ViewModel (ex: MyModelViewModel) and include it as a List<MyModelViewModel> inside MyViewModel to be used as the ItemsSource.
Going by MVVM, if you feel you should have a corresponding View for it, you can extract out the DataTemplate of the ItemsControl to a new XMAL.
You need to implement IDataErrorInfo on your Model, not your ViewModel.
As it is right now, your a validation check is throwing an error when you try and validate the property MyViewModel.NumberTrained, which doesn't exist, so the validation error never gets called.

Resources