Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ListViewItem IsSelected Binding - Works for WPF, but not for WinRT

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?

like image 594
David Klimek Avatar asked Apr 13 '13 23:04

David Klimek


2 Answers

WinRT doesn't support bindings in setters at all as of Windows 8.0. Bing for workarounds.

like image 197
Filip Skakun Avatar answered Nov 12 '22 11:11

Filip Skakun


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

like image 26
dcastro Avatar answered Nov 12 '22 12:11

dcastro