I have a ListView with a template containing an Image and a Text.
When i refresh the list, sometimes, some images are not displayed (randomly)
If i scroll down the list and scroll up to see the item again, image will appear magically, so the Image is set correctly to the item.
I tried ListViewCachingStrategy.RecycleElement and ListViewCachingStrategy.RetainElement, no difference.
<ListView ItemsSource="{Binding Path=Results}"
HasUnevenRows="True"
IsPullToRefreshEnabled="True"
RefreshCommand="{Binding RefreshCommand}"
IsRefreshing="{Binding IsBusy, Mode=OneWay}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/> <!-- Image -->
<ColumnDefinition Width="3*"/> <!-- Message -->
<ColumnDefinition Width="1*"/> <!-- Date -->
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!-- Image -->
<Grid Grid.Column="0" Grid.Row="0" Grid.RowSpan="3"
HorizontalOptions="FillAndExpand"
BackgroundColor="#40000000">
<Image Source="{Binding Thumbnail}"
VerticalOptions="Center"
Aspect="AspectFill"/>
</Grid>
private async Task RefreshAsync()
{
try
{
IsBusy = true;
_results.Clear();
_results.AsyncQueryStarted();
var result = await _client.QueryAsync<ReportResult>(_report);
if (result != null)
{
try
{
var items = new List<ResultItem>(result.Events.Count);
foreach (var res in result.Events)
{
result.EntityLookup.TryGetValue(res.Guid, out var name);
var item = new ResultItem(res.Guid, name, res.EventTime, res.Notes);
items.Add(item);
}
int itemWidth = (int)(PageWidth / ItemsPerRow);
// Sort them by timestamp (latest first)
foreach (var item in items.OrderByDescending(x => x.Timestamp))
{
item.ItemWidth = itemWidth;
_results.Add(item);
}
}
catch { }
_results.AsyncQueryFinished(_results.Count == 0);
RefreshView();
}
}
catch (Exception ex)
{
Application.Current.Trace("Error occured while refreshing", ex, this);
}
finally
{
_requiresRefresh = false;
IsBusy = false;
}
}
private async void RefreshView()
{
int itemWidth = (int)(PageWidth / ItemsPerRow);
var requests = new List<ThumbnailItem>();
var results = new List<ResultItem>(_results);
foreach (var item in results)
{
item.ItemWidth = itemWidth;
// Try to retrieve it from cache
item.Thumbnail = await _thumbnailService.RetrieveAsync(item.Id, null, item.Timestamp);
}
}
Related
I followed the below tutorial
https://xamarinhelp.com/use-camera-take-photo-xamarin-forms/
(I installed version 3.1.3)
But I get this error:
CS0103 The name 'PhotoImage' does not exist in the current context
In this method:
private async void CameraButton_Clicked(object sender, EventArgs e)
{
var photo = await Plugin.Media.CrossMedia.Current.TakePhotoAsync(new plugin.Media.Abstractions.StoreCameraMediaOptions() { });
if (photo != null)
PhotoImage.Source = ImageSource.FromStream(() => { return photo.GetStream(); });
}
I am new to Xamarin and am not sure how to fix this.
From shared sample , you can have a check whether Xaml contains PhotoImage :
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Image x:Name="PhotoImage" />
<Button x:Name="CameraButton" Text="Take Photo" Grid.Row="1" />
</Grid>
I have a gesture to swipe left and I would like the label to appear like it is swiped off the screen.
How does one achieve this with xamarin forms?
For example in the picture below the item selected was "Check the trains schedule London - Paris"
When the item is selected the text appears off the screen. I would like to achieve the same
Create a lovely grid with 2 columns.
EDIT This grid is going to sit inside a horizontal scrollview. This is what makes the trick to go out of the screen possible.
Now if you want to prohibit user from manually scrolling your ScrollView use a custom renderer. But this is not needed in case you want the user to be able to swipe the control left-right, it then acts rather naturally. So in XAML code below you can just use ScrollView instead of controls:DisabledScrollView.
1st column is what you have on the screen.
2nd column is what is hidden out of the screen.
First col width = ScreenSize. Define in code as it can change dynamically on screen rotation.
Second column width - at will. In your case it's small for just this TrashCan icon.
I'm managing it in the OnSize changed event for the grid, the invoked OnSizeChanged_TitleBarMain from XAML:
cNavBarSlider.ColumnDefinitions.Clear();
cNavBarSlider.ColumnDefinitions.Add(
new ColumnDefinition { Width = new GridLength(ScreenWidth, GridUnitType.Absolute) }
);
cNavBarSlider.ColumnDefinitions.Add(
new ColumnDefinition { Width = new GridLength(ScreenWidth - popupSearchOffset, GridUnitType.Absolute) }
);
//reposition scroll if needed (on screen rotation)
if (IsPopupSearchVisible)
{
await cNavBarSlider.TranslateTo(-ScreenWidth + popupSearchOffset, 0, 0, null);
}
Slide this table left-right with TranslateTo, in my case it was:
await cNavBarSlider.TranslateTo(-cTitleBarMain.Width + popupSearchOffset, 0, PopupOptionsTimeIn, Easing.CubicInOut);
Both IconSearch and Cancel hotspots (using hotspots and i want larger area to respond to touch, instead of user trying to tap some small icon or small word) invoke same method:
private bool _tapped;
//-------------------------------------------------------------
private async void OnTapped_SearchIcon(object sender, EventArgs e)
//-------------------------------------------------------------
{
if (_tapped) return;
_tapped = true;
if (!IsPopupSearchVisible) await PopupSearchShow();
else await PopupSearchHide();
_tapped = false;
}
//-------------------------------------------------------------------
public async Task PopupSearchShow()
//-------------------------------------------------------------------
{
await PopupSearchInit();
await cNavBarSlider.TranslateTo(-cTitleBarMain.Width + popupSearchOffset, 0, PopupOptionsTimeIn, Easing.CubicInOut);
IsPopupSearchVisible = true;
ControlSearchEntry.Focus();
}
//-------------------------------------------------------------------
public async Task PopupSearchHide(bool animate = true)
//-------------------------------------------------------------------
{
uint d = PopupOptionsTimeOut;
if (!animate) d = 0;
await cNavBarSlider.TranslateTo(0, 0, d, Easing.CubicInOut);
IsPopupSearchVisible = false;
}
The XAML scheme to play with:
<!-- SWIPE CONTAINER -->
<controls:DisabledScrollView Orientation="Horizontal" VerticalOptions="FillAndExpand">
<Grid
x:Name="cNavBarSlider"
ColumnSpacing="0"
HorizontalOptions="Fill">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<!-- this in on screen, going to swipe -->
<Grid
x:Name="cTitleBarMain"
Grid.Column="0"
SizeChanged="OnSizeChanged_TitleBarMain">
<!-- put ur stuff here -->
</Grid>
<StackLayout
x:Name="cTitleBarSearch"
Grid.Column="1"
Orientation="Horizontal">
<!-- your hidden content to appear put here --!>
<StackLayout>
</Grid>
</controls:DisabledScrollView>
EDIT
Here's your code in list (Android emulator) note you can implement swipes to limit the scrolling coordinates, to make it sticky to bounds:
Listview:
<ListView
x:Name="MainList"
ItemsSource="{Binding Items}"
BackgroundColor="{StaticResource ColorListView}"
HasUnevenRows="False"
RowHeight="40"
HorizontalOptions="FillAndExpand"
IsVisible="{Binding IsOffline, Converter={StaticResource not}}"
ItemSelected="MainList_OnItemSelected"
RefreshCommand="{Binding ForceRefreshCommand}">
<ListView.SeparatorColor>
<OnPlatform
x:TypeArguments="Color"
WinPhone="{StaticResource ListSeparator}"
iOS="{StaticResource ListSeparator}" />
</ListView.SeparatorColor>
<ListView.ItemTemplate>
<DataTemplate>
<appoMobi:CellJessica/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Cell XAML:
<?xml version="1.0" encoding="utf-8" ?>
<ViewCell xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="AppoMobi.CellJessica"
x:Name="MyViewCell">
<!-- SWIPE CONTAINER -->
<StackLayout SizeChanged="OnSizeChanged_TitleBarMain" x:Name="cCell" HorizontalOptions="FillAndExpand">
<ScrollView x:Name="scrollView"
Orientation="Horizontal"
VerticalOptions="FillAndExpand">
<Grid x:Name="cNavBarSlider"
ColumnSpacing="0"
HorizontalOptions="Fill">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<!-- this in on screen, going to swipe -->
<Grid
x:Name="cTitleBarMain"
Grid.Column="0">
<!-- put ur stuff here -->
<Label x:Name="txtLabel" TextColor="Black" />
</Grid>
<StackLayout
x:Name="cTitleBarSearch"
Grid.Column="1"
Orientation="Horizontal">
<Image Source="cake" HeightRequest="35" WidthRequest="35" VerticalOptions="Center" HorizontalOptions="Start" />
</StackLayout>
</Grid>
</ScrollView>
</StackLayout>
</ViewCell>
Cell Code:
public partial class CellJessica
{
public CellJessica()
{
InitializeComponent();
}
//-------------------------------------------------------------
protected override void OnBindingContextChanged()
//-------------------------------------------------------------
{
SetupCell();
base.OnBindingContextChanged();
}
private bool first_setup = true;
//-------------------------------------------------------------
public void SetupCell()
//-------------------------------------------------------------
{
var item = BindingContext as CSalonListItemEx;
if (item == null) return;
txtLabel.Text = item.Name;
}
private bool _titlebar_changingsize = false;
private double popupSearchOffset = 0;
//-------------------------------------------------------------------
private async void OnSizeChanged_TitleBarMain(object sender, EventArgs e)
//-------------------------------------------------------------------
{
if (_titlebar_changingsize) return;
_titlebar_changingsize = true;
cNavBarSlider.ColumnDefinitions.Clear();
cNavBarSlider.ColumnDefinitions.Add(
new ColumnDefinition { Width = new GridLength(cCell.Width, GridUnitType.Absolute) }
);
cNavBarSlider.ColumnDefinitions.Add(
//new ColumnDefinition { Width = new GridLength(cCell.Width - popupSearchOffset, GridUnitType.Absolute) }
new ColumnDefinition { Width = new GridLength(40, GridUnitType.Absolute) }
);
//todo
//reposition scroll if rotated when hidden barea is shown
//if (IsPopupSearchVisible)
//{
// await cNavBarSlider.TranslateTo(-cCell.Width + 40, 0, 0, null);
//}
_titlebar_changingsize = false;
}
}
I am working on Xamarin forms,I need to display data from database on form load.
So I want to display Activity indicator when database operation is taking time.
I am setting ActivityIndicator to true on constructor load andat the end setting it to false.
But its not showing
Here is code
Xaml is as below
<ContentPage.Content>
<StackLayout VerticalOptions="StartAndExpand" Padding="5,5,5,5">
<ListView HasUnevenRows="True" RowHeight="100" HeightRequest="-1" x:Name="ListViewAppointments" VerticalOptions="StartAndExpand">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid Padding="20,0,20,0" ColumnSpacing="20">
<Grid.RowDefinitions>
<RowDefinition Height="40"></RowDefinition>
<RowDefinition Height="40"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="40"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="40"></ColumnDefinition>
</Grid.ColumnDefinitions>
<!--<BoxView Color="#f7f7f7" Grid.Column="0" Grid.RowSpan="2"/>
<BoxView Color="#ffffff" Grid.Column="1" Grid.RowSpan="2"/>-->
<Image Grid.RowSpan="2" Grid.Column="0" Source="documenticon.png" Aspect="AspectFit"></Image>
<Label TextColor="#00344e" FontAttributes="Bold" Text="{Binding ReportName}" Grid.Row="0" Grid.Column="1" VerticalTextAlignment="End"></Label>
<Label TextColor="#0073ae" Text="{Binding PrintDate}" Grid.Row="1" Grid.Column="1" VerticalTextAlignment="Start"></Label>
<Image Grid.RowSpan="2" Grid.Column="2" Source="downloadicon.png" Aspect="AspectFit"></Image>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<ActivityIndicator x:Name="ActLoder" HorizontalOptions="CenterAndExpand" Color="#ffffff" VerticalOptions="CenterAndExpand" />
</StackLayout>
</ContentPage.Content>
and code behind
public partial class CurrentDocuments : ContentPage
{
public CurrentDocuments()
{
InitializeComponent();
new Task(Initializer).Start();
}
public async void Initializer()
{
ShowLoader(true);
NavigationPage.SetBackButtonTitle(this, "");
Title = "CURRENT DOCUMENTS";
DocumentsResponse appointsData = null;
await Task.Run(async () =>
{
appointsData = await GetCurrentDocuments();
}).ContinueWith(_ =>
{
Device.BeginInvokeOnMainThread(() => {
ListViewAppointments.ItemsSource = appointsData.ListOfDocuments;
ShowLoader(false);
});
});
}
private async Task<DocumentsResponse> GetCurrentDocuments()
{
DocumentManager manager = new DocumentManager();
var result = await manager.GetCurrentDocuments(Application.Current.Properties["SessionId"].ToString());
return result;
}
public async void ShowLoader(bool isVisible)
{
ActLoder.IsRunning = isVisible;
ActLoder.IsVisible = isVisible;
ActLoder.IsEnabled = true;
}
}
GetCurrentDocuments is returning a Task<DocumentsResponse> and you are not awaiting it to activate that Task.
var appointsData = await GetCurrentDocuments();
But, you should not await in an .ctor.
Something like this will get you started (I did this on the fly, so correct any typos/syntax errors/etc:
public partial class CurrentDocuments : ContentPage
{
public CurrentDocuments()
{
InitializeComponent();
new Task(Initializer).Start();
}
public async void Initializer()
{
ShowLoader(true);
NavigationPage.SetBackButtonTitle(this, "");
Title = "CURRENT DOCUMENTS";
Task<DocumentsResponse> appointsData;
await Task.Run(async () =>
{
appointsData = await GetCurrentDocuments();
}).ContinueWith(_ =>
{
Device.BeginInvokeOnMainThread(() => {
ListViewAppointments.ItemsSource = appointsData;
ShowLoader(false);
});
});
}
public void ShowLoader(bool isVisible)
{
ActLoder.IsRunning = isVisible;
ActLoder.IsVisible = isVisible;
ActLoder.IsEnabled = true;
}
public async Task<DocumentsResponse> GetCurrentDocuments()
{
DocumentManager manager = new DocumentManager();
var result = await manager.GetCurrentDocuments(Application.Current.Properties["SessionId"].ToString());
return result;
}
}
I have this list of objects that needs to be separated into two columns. Then I use this template for every object of the list:
<DataTemplate x:Key="UnderlyingRealTimeExchangeRatesLongListSelector">
<Grid Background="{Binding PriceChanged, Converter={StaticResource PriceChangedToBackgroundConverter}}"
Margin="0,2.5,5,2.5" Tap="RealTimeElement_Tapped">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock x:Name="txtUnderlyingName" Text="{Binding Name}" Foreground="White"
Style="{StaticResource NormalFontStyle}" HorizontalAlignment="Left"
Margin="5" FontSize="25" Padding="10" TextWrapping="Wrap"/>
<Image Grid.Column="1"
Source="{Binding Path= Image, Converter={StaticResource ImageToFlagConverter}}"
Height="30"></Image>
<TextBlock x:Name="txtUnderlyingPrice" Text="{Binding Price, StringFormat='0:N2'}"
Grid.Row="1" Grid.ColumnSpan="2" Foreground="#FFD300"
Style="{StaticResource LightFontStyle}" FontSize="40"
HorizontalAlignment="Right" VerticalAlignment="Center" Padding="10"/>
</Grid>
</DataTemplate>
<phone:LongListSelector x:Name="llsRealTimeCurrencies1" Grid.Column="0" Margin="0,15,0,32"
ItemTemplate="{StaticResource UnderlyingRealTimeExchangeRatesLongListSelector}"
Visibility="Collapsed"/>
<phone:LongListSelector x:Name="llsRealTimeCurrencies2" Grid.Column="1" Margin="0,15,0,32"
ItemTemplate="{StaticResource UnderlyingRealTimeExchangeRatesLongListSelector}"
Visibility="Collapsed"/>
Here is the converter:
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
//Returns The flag needed
if (value != null)
{
string image = value.ToString().ToLower();
string flag = "Assets\\flags\\" + image + "_flag.png";
return Path.GetFullPath(flag);
}
else
{
return null;
}
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
Here is the code behind the previous part:
private void SetAndShowCorrectRealTimeList<T>(LongListSelector[] list, IList<T> collection)
{
//and make sure the grid holding the lists is visible
grdRealtimeLists.Visibility = System.Windows.Visibility.Visible;
List<LongListSelector> lists =
new List<LongListSelector>()
{
llsRealTimeCommodities1,
llsRealTimeCommodities2,
llsRealTimeCurrencies1,
llsRealTimeCurrencies2,
llsRealTimeIndecies1,
llsRealTimeIndecies2,
llsRealTimeWatchList1,
llsRealTimeWatchList2
};
foreach (var item in lists.Except(list))
{
item.Visibility = System.Windows.Visibility.Collapsed;
}
for (int i = 0; i < list.Length; i++)
{
list[i].Visibility = Visibility.Visible;
List<T> result = collection.Where((item, index) => index % 2 == i).ToList();
list[i].ItemsSource = result;
}
}
The funny part is that it displays the images on the left column, but doesn't on the right. As a matter of fact, it doesn't even gets in the converter for the second column. Thank you!!!
Bind image source like this.
<Image Grid.Column="1" Height="30">
<Image.Source>
<BitmapImage UriSource="{Binding Path=Image, Converter={StaticResource ImageToFlagConverter}}" />
</Image.Source>
</Image>
Check to see if your code has all the right elements -
llsRealTimeCurrencies1, llsRealTimeCurrencies2. Those are the lists that we use to bind the template to:
private async void Currencies_Tapped(object sender, System.Windows.Input.GestureEventArgs e)
{
mainViewModel.RealTimeViewModel.IsWatchListSettingsVisible = false;
ApplyForegroundFont(sender, realtimeTabs);
FrameworkElement parent = (FrameworkElement)((TextBlock)sender).Parent;
ApplyBackgroundColor(parent, realtimeTabsGrid);
if (!mainViewModel.RealTimeViewModel.CurrencyExchangeRates.Any())
{
if (mainViewModel.RealTimeViewModel.Realtime != null &&
mainViewModel.RealTimeViewModel.Realtime.Underlyings != null &&
mainViewModel.RealTimeViewModel.Realtime.Underlyings.Any())
{
mainViewModel.RealTimeViewModel.InitializeCurrencies();
}
else
{
mainViewModel.RealTimeViewModel.LoadProductsOrUnderlyingsFromDb<Currency>(mainViewModel.RealTimeViewModel.CurrencyExchangeRates);
}
}
if (!App.Settings.Contains(currenciesWereSaved))
{
App.Settings.Add(currenciesWereSaved, "");
App.Settings.Save();
await Task.Factory.StartNew(() =>
mainViewModel.RealTimeViewModel.SaveUnderlyingsAndProducts<Currency>(mainViewModel.RealTimeViewModel.CurrencyExchangeRates));
}
SetAndShowCorrectRealTimeList(new LongListSelector[] { llsRealTimeCurrencies1, llsRealTimeCurrencies2 }, mainViewModel.RealTimeViewModel.CurrencyExchangeRates);
GoogleAnalytics.EasyTracker.GetTracker().SendEvent("Real time", "click", "Currencies", 0);
MyBindableBase.LightstreamerClientInstance.Subscribe(mainViewModel.RealTimeViewModel.CurrencyExchangeRates.Cast<IRealtimeProperty>().ToList());
}
I am developing a WP7 app that contains a LongListSelector. Within the ItemTemplate there is a ListPicker. I select a value from the ListPicker for the first item in the LongListSelector, then select a value from the ListPicker for the 2nd item. If I then scroll down the page and back to the top again, the value I selected in the ListPicker for the 1st item will be reset (SelectedIndex=0).
I have put code in the Link and Unlink events of the LongListSelector to write to the output window and I have found that when the 1st item unlinks (due to scrolling down the page), the ListPicker value is what I selected but as soon as the link event fires (due to scrolling back up the page) for the 1st item the value is reset.
Im using ObserableCollection and implement the INPC interface for my objects and the ViewModel updates when the ListPicker selection is changed.
How can I ensure that the value in the ListPickers are retaining during scrolling of the LongListSelector?
MainPage.xaml
<phone:PhoneApplicationPage
x:Class="LongListSelector.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="5000"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="Portrait" Orientation="Portrait"
shell:SystemTray.IsVisible="True"
xmlns:toolkit="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Toolkit">
<phone:PhoneApplicationPage.Resources>
<DataTemplate x:Name="occurrenceItemTemplate">
<Grid>
<StackPanel Orientation="Vertical" Margin="5,0,0,0" >
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Name="tbkEventDateTime" Grid.Row="0" Grid.Column="0"
Text="{Binding ItemNumber}"
Style="{StaticResource PhoneTextSmallStyle}" />
<!--<TextBox Name="txtEventDateTime" Grid.Row="1" Grid.Column="0"
Text="{Binding Result}" />-->
<toolkit:ListPicker Name="lpkResult" Margin="12,0,12,12"
Grid.Row="1" Grid.Column="0"
ItemsSource="{Binding TestItemResultList, Mode=OneTime}"
SelectedIndex="{Binding Result, Mode=TwoWay}"
CacheMode="BitmapCache">
<toolkit:ListPicker.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Text}" />
</DataTemplate>
</toolkit:ListPicker.ItemTemplate>
</toolkit:ListPicker>
</Grid>
</StackPanel>
</Grid>
</DataTemplate>
</phone:PhoneApplicationPage.Resources>
<!--LayoutRoot is the root grid where all page content is placed-->
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!--TitlePanel contains the name of the application and page title-->
<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
<TextBlock x:Name="ApplicationTitle" Text="MY APPLICATION" Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock x:Name="PageTitle" Text="page name" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
</StackPanel>
<!--ContentPanel - place additional content here-->
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0" VerticalAlignment="Stretch">
<toolkit:LongListSelector x:Name="lstOutstandingOccurrences"
Margin="0,12,0,0" Padding="0,0,0,24"
ItemTemplate="{StaticResource occurrenceItemTemplate}"
ItemsSource="{Binding TestItemCollection, Mode=TwoWay}"
IsFlatList="True" ShowListHeader="False" >
</toolkit:LongListSelector>
</Grid>
</Grid>
MainPage.xaml.cs
public partial class MainPage : PhoneApplicationPage
{
private TestItemViewModel _vm;
public TestItemViewModel ViewModel
{
get
{
if (_vm == null)
_vm = new TestItemViewModel();
return _vm;
}
private set
{
_vm = value;
}
}
// Constructor
public MainPage()
{
InitializeComponent();
this.lstOutstandingOccurrences.Link += new EventHandler<LinkUnlinkEventArgs>(lstOutstandingOccurrences_Link);
this.lstOutstandingOccurrences.Unlink += new EventHandler<LinkUnlinkEventArgs>(lstOutstandingOccurrences_Unlink);
this.DataContext = this.ViewModel;
}
void lstOutstandingOccurrences_Link(object sender, LinkUnlinkEventArgs e)
{
var item = e.ContentPresenter.Content as TestItem;
Debug.WriteLine("Link event for ItemNumber {0} = {1}", item.ItemNumber, item.Result);
}
void lstOutstandingOccurrences_Unlink(object sender, LinkUnlinkEventArgs e)
{
var item = e.ContentPresenter.Content as TestItem;
Debug.WriteLine("Unlink event for ItemNumber {0} = {1}", item.ItemNumber, item.Result);
}
}
TestItemViewModel.cs
public class TestItemViewModel : BaseINPC
{
public ObservableCollection<TestItem> TestItemCollection
{
get;
private set;
}
// Constructor
public TestItemViewModel()
{
this.TestItemCollection = new ObservableCollection<TestItem>();
CreateTestData(20);
}
public void CreateTestData(int totalItems)
{
//create test data for long list selector.
for (int i = 1; i <= totalItems; i++)
{
this.TestItemCollection.Add(new TestItem(i, 0));
}
}
}
Models
public class ListHelperListItem
{
public int Value { get; set; }
public string Text { get; set; }
}
public class TestItem : BaseINPC
{
public TestItem(int ItemNumber, int Result)
{
this.ItemNumber = ItemNumber;
this.Result = Result;
}
public int ItemNumber { get; set; }
private int _Result;
public int Result
{
get
{
return _Result;
}
set
{
//if statement is for debugging purposes only.
if (this.ItemNumber == 1)
{
_Result = value;
}
_Result = value;
RaisePropertyChanged("Result");
}
}
private List<ListHelperListItem> _TestItemResultList;
public List<ListHelperListItem> TestItemResultList
{
get
{
_TestItemResultList = new List<ListHelperListItem>();
_TestItemResultList.Add(new ListHelperListItem { Value = 0, Text = " " });
_TestItemResultList.Add(new ListHelperListItem { Value = 1, Text = "Yes" });
_TestItemResultList.Add(new ListHelperListItem { Value = 2, Text = "No" });
_TestItemResultList.Add(new ListHelperListItem { Value = 3, Text = "Ignore" });
return _TestItemResultList;
}
}
}
Thanks for your help!