Milan Henkrich
Milan Henkrich

Reputation: 67

UWP - Binding of ListViewItem IsSelected binding two way not taking initial value

Hello Guys I am struggling with this one. I have list called "ROOT" I apply to this list's ItemTemplate "RootTemplate". Within "RootTemplate" I have another list "BRANCH" with another template "BranchTemplate", and what I am trying to achieve is to pre-select some of them listViewItems inside of BRANCH list.

<ResourceDictionary
    <DataTemplate x:Key="RootTemplate" >
    <ListViewItem>
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto" MinWidth="0"/>
                <ColumnDefinition Width="Auto" MinWidth="0"/>
            </Grid.ColumnDefinitions>
            <ListView ItemsSource="{Binding Branches}" ItemTemplate="{StaticResource BranchTemplate}" SelectionMode="Multiple"/>
        </Grid>
    </ListViewItem>
</DataTemplate>
    <DataTemplate x:Key="BranchTemplate">
    <ListViewItem IsSelected="{Binding IsChecked, Mode=TwoWay}">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Width="Auto"/>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"/>
            </Grid.ColumnDefinitions>
            <TextBlock Text="{Binding Name}"/>
        </Grid>
    </ListViewItem>
</DataTemplate>

My ViewModel is simple

public class Root: ReactiveObject
{
    public ObservableCollectionExtended<Branch> Branches{ get; } = new ObservableCollectionExtended<Branch>();}

public class Branch: ReactiveObject
{
    private bool _isChecked = true;
    public bool IsChecked
    {
        get => _isChecked;
        set
        {
            this.RaiseAndSetIfChanged(ref _isChecked, value);
        }
    }
    private string _name;
    public string Name
    {
        get => _name;
        set
        {
            this.RaiseAndSetIfChanged(ref _name, value);
        }
    }}

In BranchTemplate I am using binding with IsSelected to IsChecked property. It works fine, when I click on list IsChecked is changed accordingly, also when I (during-run time) change IsChecked property then I can see change reflected on UI. But I can't initialize IsChecked to true (as you can see code). Even if I do so, then when I run application IsChecked it automatically set back to false, and in UI listItems are not selected.

Upvotes: 0

Views: 215

Answers (1)

YanGu
YanGu

Reputation: 3032

Referring to the document (which mentions "If you style the control template, do not try to bind properties like IsSelected or Background properties on the ListViewItemPresenter, perhaps to implement your own selection binding system, since your binding may be replaced by the control's internal mechanism."), the reason why the IsSelected property of ListViewItem could not be initialized may be the initialization binding is replaced with the control's internal mechanism.

As you mentioned, you could set the value of IsChecked in code to change the IsSelected property of a ListViewItem and the value of IsChecked will be changed when you click an item in ListView, which indicates that the two-way data binding can work. Therefore, you could force certain items of ListView named BRANCH to be selected by adding a Loading event to resolve the initialization binding of IsSelected property.

For example:

……
<ListView ItemsSource="{Binding Branches}" ItemTemplate="{StaticResource BranchTemplate}" SelectionMode="Multiple" Loading="ListView_Loading"/>
……
private void ListView_Loading(FrameworkElement sender, object args)
{
    var list = sender as ListView;
    var root = list.DataContext as Root;  //Adjust the type to your scenario
    for (int i = 0; i < root.Branches.Count; i++)
    {
        var item = root.Branches.ElementAt(i);
        if (item.IsChecked == true)
        {
            list.SelectedItems.Add(list.Items.ElementAt(i));
        }
    }
}

Upvotes: 1

Related Questions