Reputation: 2488
I want to display a list of objects in a LongListSelector, and format them with a DataTemplate. To properly use MVVM I'd like to have a ViewModel in this DataTemplate.
Creating of this ViewModel is no problem, but how do I pass the Item to the ViewModel?
I'm using this code:
<Controls:LongListSelector
ItemsSource="{Binding MyItems}" Margin="0" HorizontalAlignment="Stretch"
HorizontalContentAlignment="Stretch" >
<Controls:LongListSelector.DataContext>
<viewmodel:MyListOfItemsViewModel />
</Controls:LongListSelector.DataContext>
<Controls:LongListSelector.ItemTemplate>
<DataTemplate>
<StackPanel x:Name="CurTemplate">
<Grid Margin="10" >
<Grid.DataContext>
<viewmodel:MyViewModel MyItem="{Binding Path=DataContext,ElementName=CurTemplate}" />
</Grid.DataContext>
But alas, the only thing that is set for MyItem is null
, and this is never updated to the real value. I found out that later in the process (after the initial setting of MyItem
CurTemplate does have a valid DataContext, but this is not sent to my ViewModel. Am I missing something here?
For completeness the code for MyViewModel:
public static DependencyProperty MyItemProperty = DependencyProperty.Register("MyItem", typeof(object), typeof(MyViewModel), new PropertyMetadata("asd", ItemChanged));
private static void ItemChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
System.Diagnostics.Debugger.Break(); // to set when something is set
// called once, NewValue is null
}
public object MyItem
{
get
{
return (object)GetValue(MyItemProperty);
}
set
{
SetValue(MyItemProperty, value);
RaisePropChangeEvent("MyItem");
}
}
I did a lot of searching and fiddling around, but I'm pretty sure this is just a minor thing that is missing here. I would be very glad if you could help me out here...
EDIT: Solved
I solved my problem by using {Binding Path=Content,RelativeSource={RelativeSource Mode=TemplatedParent}}
as binding for the viewmodel. I have no idea why this works with Content
, but not with DataContext
...
Thanks for your help, robertftw, your linked post brought me to the right track!
Upvotes: 1
Views: 3012
Reputation: 6142
What are you trying to do? Do you just want to interact to a selection change and have the selected item in the LongListSelector being pushed to the ViewModel?
If so... I'm using an extension for this scenario. The only thing with such an extension is that setting the current item from the ViewModel is not ported back to the view ( but didn't need that ).
The ViewModel change is
public RelayCommand<MyItemType> ViewModelCommand
The XAML change is
<phone:LongListSelector extensions:LongListSelectorExtension.Command="{Binding ViewModelCommand}" />
The extension
public static class LongListSelectorExtension
{
public static readonly DependencyProperty CommandProperty =
DependencyProperty.RegisterAttached("Command",
typeof(ICommand), typeof(LongListSelectorExtension),
new PropertyMetadata(null, OnCommandChanged));
public static ICommand GetCommand(LongListSelector selector)
{
return (ICommand)selector.GetValue(CommandProperty);
}
public static void SetCommand(LongListSelector selector, ICommand value)
{
selector.SetValue(CommandProperty, value);
}
private static void OnCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var selector = d as LongListSelector;
if (selector == null)
{
throw new ArgumentException(
"You must set the Command attached property on an element that derives from LongListSelector.");
}
var oldCommand = e.OldValue as ICommand;
if (oldCommand != null)
{
selector.SelectionChanged -= OnSelectionChanged;
}
var newCommand = e.NewValue as ICommand;
if (newCommand != null)
{
selector.SelectionChanged += OnSelectionChanged;
}
}
private static void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
{
var selector = sender as LongListSelector;
var command = GetCommand(selector);
if (command != null && selector.SelectedItem != null)
{
command.Execute(selector.SelectedItem);
}
selector.SelectedItem = null;
}
}
Upvotes: 1
Reputation: 2461
Seems like the problem I had a few days ago: Binding does not update usercontrol property correctly MVVM
public static DependencyProperty MyItemProperty = DependencyProperty.Register("MyItem", typeof(object), typeof(MyViewModel), new PropertyMetadata(string.Empty, ItemChanged));
private static void ItemChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var obj = d as MyViewModel;
obj.RaisePropChangeEvent("MyItem");
}
The problem I had is that the set of MyItem isn't actually called.
Upvotes: 1