Reputation: 205
I'm trying to bind the IsSelected property of a ListViewItem to a property in a ViewModel. It works fine in WPF, but in Windows RT the IsSelected property is never getting set.
public class Item : INotifyPropertyChanged
{
private readonly string name;
private bool isSelected;
public event PropertyChangedEventHandler PropertyChanged;
public bool IsSelected
{
get { return isSelected; }
set { isSelected = value; RaisePropertyChanged("IsSelected"); }
}
public string Name { get { return name; } }
public Item(string name)
{
this.name = name;
}
protected void RaisePropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if (handler != null)
handler.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
public class ViewModel
{
private readonly ObservableCollection<Item> items = new ObservableCollection<Item>(Enumerable.Range(0, 10).Select(p => new Item(p.ToString())));
public ObservableCollection<Item> Items { get { return items; } }
}
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
DataContext = new ViewModel();
}
}
xaml:
<StackPanel Orientation="Horizontal">
<ListView ItemsSource="{Binding Path=Items}" SelectionMode="Multiple">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="IsSelected" Value="{Binding Path=IsSelected, Mode=TwoWay}"/>
</Style>
</ListView.ItemContainerStyle>
</ListView>
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Name}"/>
</DataTemplate>
</ListView.ItemTemplate>
</StackPanel>
I'm able to click on the items on the screen, but the IsSelected property isn't propagating to the ViewModel. Any ideas why?
Upvotes: 10
Views: 6706
Reputation: 31724
WinRT doesn't support bindings in setters at all as of Windows 8.0. Bing for workarounds.
Upvotes: 3
Reputation: 68640
A good and easy way to do this is to subclass ListView
public class MyListView : ListView
{
protected override void PrepareContainerForItemOverride(Windows.UI.Xaml.DependencyObject element, object item)
{
base.PrepareContainerForItemOverride(element, item);
// ...
ListViewItem listItem = element as ListViewItem;
Binding binding = new Binding();
binding.Mode = BindingMode.TwoWay;
binding.Source = item;
binding.Path = new PropertyPath("Selected");
listItem.SetBinding(ListViewItem.IsSelectedProperty, binding);
}
}
Alternatively, it seems you can also do it with WinRT XAML Toolkit.
<ListView
x:Name="lv"
Grid.Row="1"
Grid.Column="1"
SelectionMode="Multiple"
HorizontalAlignment="Left"
Width="500">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock
Extensions:ListViewItemExtensions.IsSelected="{Binding IsSelected}"
Extensions:ListViewItemExtensions.IsEnabled="{Binding IsEnabled}"
Text="{Binding Text}"
Margin="15,5"
FontSize="36" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Personally, I used the first approach because it's more flexible and I needed to bind a few Automation Properties.
Credits to ForInfo and ehuna: http://social.msdn.microsoft.com/Forums/windowsapps/en-US/9a0adf35-fdad-4419-9a34-a9dac052a2e3/listviewitemisselected-data-binding-in-style-setter-is-not-working
Upvotes: 4