Martin Dusek
Martin Dusek

Reputation: 1292

UWP listview binding

what is the easiest way to bind selected state of listview's item to model's boolean property?

I have model:

class Model {
    public string Name { get; set; }
    public bool Selected { get; set; }
}

And listview:

<ListView x:Name="myListView" SelectionMode="Multiple">
<ListView.ItemTemplate>
    <DataTemplate x:DataType="x:String">
        <TextBlock Text="{Binding Name}"/>
    </DataTemplate>
</ListView.ItemTemplate>

I bind items to the listview:

myListView.ItemsSource = // list of Model instances

I want the Selected property of Model to always reflect whether it is selected or not in myListView. So - by selecting/deselecting the item in myListView, it will hold the apropriate bool value or by setting Selected property myListView will select/deselect appropriate item.

Upvotes: 1

Views: 4553

Answers (2)

Grace Feng
Grace Feng

Reputation: 16652

what is the easiest way to bind selected state of listview's item to model's boolean property?

I'm not sure if this is the most easiest way, but for me I think it is the easiest way to bind SelectorItem.IsSelected property of ListViewItem to your Selected property in model. Only the problem is, we all know each item of ListView is an instance of ListViewItem, but when we use DataTemplate to build the item structure for ListViewItem, ListViewItems are not available in design-time. So my idea is to bind this property in code behind, just for example here:

<ListView x:Name="myListView" SelectionMode="Multiple" Loaded="myListView_Loaded" ItemsSource="{x:Bind Collection}">
    <ListView.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Name}" />
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

code behind:

private ObservableCollection<Model> Collection = new ObservableCollection<Model>();

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    for (int i = 0; i < 100; i++)
    {
        Collection.Add(new Model { Name = "Name " + i });
    }
}

private void myListView_Loaded(object sender, RoutedEventArgs e)
{
    IEnumerable<ListViewItem> lvItems = FindVisualChildren<ListViewItem>(myListView);
    if (lvItems != null)
    {
        foreach (ListViewItem lvitem in lvItems)
        {
            Model model = lvitem.Content as Model;
            Binding b = new Binding
            {
                Source = model,
                Path = new PropertyPath("Selected"),
                Mode = BindingMode.TwoWay,
            };
            BindingOperations.SetBinding(lvitem, ListViewItem.IsSelectedProperty, b);
        }
    }
}

private static IEnumerable<T> FindVisualChildren<T>(DependencyObject depObj) where T : DependencyObject
{
    if (depObj != null)
    {
        for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
        {
            DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
            if (child != null && child is T)
            {
                yield return (T)child;
            }

            foreach (T childOfChild in FindVisualChildren<T>(child))
            {
                yield return childOfChild;
            }
        }
    }
}

public class Model : INotifyPropertyChanged
{
    public string Name { get; set; }

    private bool _Selected;

    public bool Selected
    {
        get { return _Selected; }
        set
        {
            if (value != _Selected)
            {
                _Selected = value;
                OnPropertyChanged();
            }
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged([CallerMemberName]string propertyName = "")
    {
        if (this.PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

Upvotes: 3

Vijay Chavda
Vijay Chavda

Reputation: 862

I think the perfect way would be to implement the ListView.ItemSelectionChanged event, and iterate through each item in the list view model to set it to true for the item which is selected, false for the rest items.

However, You may want to try something like this, although honestly I'm not sure if this is the correct way:

class Model {
    public string Name { get; set; }
    public bool Selected 
    {
        get
        {
            return MyListView.SelectedItems.Count(x => x.Name == Name) > 0;
        }
    }
}

Upvotes: 0

Related Questions