I develop an app for Windows Phone 7 with using of Caliburn Micro and Reactive Extensions.
The app has a page with a ListBox control:
<Grid x:Name="ContentPanel"
Grid.Row="1"
Margin="12,0,12,0">
<ListBox ItemsSource="{Binding Items}">
<ListBox.ItemTemplate>
<DataTemplate>
<Views:ItemView Margin="0,12,0,0" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
I’m using the next ItemView as a DataTemplate:
<UserControl ...>
<Grid x:Name="LayoutRoot"
cal:Message.Attach="[Event Tap] = [Action SelectItem]">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0"
Style="{StaticResource PhoneTextLargeStyle}"
Text="{Binding Name}"
TextWrapping="Wrap" />
<TextBlock Grid.Column="1"
Foreground="{StaticResource PhoneDisabledBrush}"
Style="{StaticResource PhoneTextLargeStyle}"
Text="{Binding Id}" />
</Grid>
</UserControl>
And the corresponding ItemViewModel looks like this:
public class ItemViewModel
{
private readonly INavigationService _navigationService;
public int Id { get; private set; }
public string Name { get; private set; }
public ItemViewModel(Item item)
{
Id = item.Id;
Name = item.Name;
_navigationService = IoC.Get<INavigationService>();
}
public void SelectItem()
{
_navigationService.UriFor<MainViewModel>()
.WithParam(x => x.Id, Id)
.Navigate();
}
}
}
The ListBox populates with items:
public class ListViewModel : Screen
{
private readonly IItemsManager _itemsManager;
private List<ItemViewModel> _items;
public List<ItemViewModel> Items
{
get { return _items; }
private set
{
_items = value;
NotifyOfPropertyChange(() => Items);
}
}
public ListViewModel(IItemsManager itemsManager)
{
_itemsManager = itemsManager;
}
protected override void OnViewReady(object view)
{
base.OnViewReady(view);
Items = null;
var list = new List<ItemViewModel>();
_itemsManager.GetAll()
.SubscribeOn(ThreadPoolScheduler.Instance)
.ObserveOnDispatcher()
.Subscribe((item) => list.Add(new ItemViewModel(item)),
(ex) => Debug.WriteLine("Error: " + ex.Message),
() =>
{
Items = list;
Debug.WriteLine("Completed"));
}
}
}
And here the problems begin.
_itemsManager returns all items correctly. And all items correctly displayed in the ListBox. There is ~150 items.
When I tap on an item then SelectItem method in the corresponding ItemViewModel must be called. And all works fine for first 10-20 items in ListBox. But for all the next items SelectItem method is called in absolutely incorrect ItemViewModel. For example, I tap on item 34 and SelectItem method is called for item 2, I tap 45 – method is called for item 23, and so on. And there is no no dependence between items.
I already head breaks in search of bugs. In what could be the problem?
The solution was found after reading the discussion forum and the page in documentation of Caliburn.Micro.
All problems were because of Caliburn.Micro’s Conventions.
To solve the problem I’ve added to the
DataTempalatethe next code:cal:View.Model={Binding}. Now part of the page with theListBoxlooks like this:I think it’s not a perfect answer. So I’ll be glad if someone can provide better answer and explanation.