How to bind the IsSelected property in a DataTemplate ListViewItem

Well, I want to do ListViewItemin UWP that will change its presentation when I select it. Therefore, when choosing, we must change the property of Visibilitysome elements ListViewItem.

I found a way to do this by creating my own style ListViewItemand Binding IsSelected, like this:

<Style x:Key="VehicleListViewItemStyle" TargetType="ListViewItem" >
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="ListViewItem">
                        <Grid Background="Gray" Margin="1">
                            <Border Margin="2" Padding="10" Background="Gray" >
                                <StackPanel>
                                    <ContentPresenter x:Name="Presenter1" />
                                    <StackPanel Orientation="Horizontal" Background="Transparent" Margin="-10,0,-9,-9" VerticalAlignment="Center" x:Name="infoPanel"
                                        Visibility="{Binding IsSelected, RelativeSource={RelativeSource Mode=TemplatedParent}, Converter={StaticResource BooleanToVisibilityConverter}}">
                                        <TextBlock Text="{Binding  DeviceID}/>                                                                            </StackPanel>
                                </StackPanel>
                            </Border>
                            <Border BorderThickness="1" BorderBrush="Orange" Visibility="{Binding IsSelected, RelativeSource={RelativeSource Mode=TemplatedParent}, Converter={StaticResource BooleanToVisibilityConverter}}"/>
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>  

It works well, but in this way I cannot link the text DeviceID.

Another way to create DataTemplate:

<DataTemplate x:Key="monitoringListViewItem" x:Name="item">
            <Grid Background="Gray" Margin="1" Width="300" >
                <StackPanel>
                    <ContentPresenter x:Name="Presenter"/>
                    <StackPanel Orientation="Horizontal">
                        <Image Source="/Assets/14th_crane_stop.png" Height="50" Width="50" Stretch="Uniform"/>
                        <StackPanel Orientation="Vertical" Margin="25,0,0,0 " 
                                    Visibility="{Binding IsSelected, RelativeSource={RelativeSource Mode=TemplatedParent}, Converter={StaticResource BooleanToVisibilityConverter}}"
                                    >
                            <TextBlock Text="{Binding DeviceID}" Style="{StaticResource VehicleTextStyle}"/>
                            <TextBlock Text="{Binding Mark}" Style="{StaticResource VehicleTextStyle}"/>
                        </StackPanel>
                    </StackPanel>
                </StackPanel >
            </Grid>
        </DataTemplate>

Now I can bind the text correctly, but I can not bind the property IsSelected. I tried to do this with various modes, but it still does not work, because I cannot use the key TemplatedParentinside the DataTemplate.

I need answers:

- ? - IsSelected ?

+4
1

ListViewItem, ( , ..).

Mode=TemplatedParent , ListViewItemPresenter, ListViewItem ( -).

, , .

#

public class NotifyPropertyChangedBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged([CallerMemberName] string propertyName = "")
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    protected bool SetProperty<T>(ref T property, T value, [CallerMemberName] string propertyName = "")
    {
        if (EqualityComparer<T>.Default.Equals(property, value))
        {
            return false;
        }

        property = value;
        OnPropertyChanged(propertyName);
        return true;
    }
}

public class Item : NotifyPropertyChangedBase
{
    private string text;
    public string Text
    {
        get { return text; }
        set { SetProperty(ref text, value); }
    }

    private bool isSelected;
    public bool IsSelected
    {
        get { return isSelected; }
        set { SetProperty(ref isSelected, value); }
    }
}

public class MainPageViewModel : NotifyPropertyChangedBase
{
    public List<Item> Items { get; set; }

    private Item selectedItem;
    public Item SelectedItem
    {
        get { return selectedItem; }
        set
        {
            if (selectedItem != value)
            {
                if (selectedItem != null)
                {
                    selectedItem.IsSelected = false;
                }

                SetProperty(ref selectedItem, value);

                if (selectedItem != null)
                {
                    selectedItem.IsSelected = true;
                }
            }
        }
    }

    public MainPageViewModel()
    {
        Items = new List<Item>()
        {
            new Item() { Text = "Apple" },
            new Item() { Text = "Banana" },
        };
    }
}

MainPage.xaml

<ListView ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem, Mode=TwoWay}">
    <ListView.ItemContainerStyle>
        <Style TargetType="ListViewItem">
            <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
        </Style>
    </ListView.ItemContainerStyle>
    <ListView.ItemTemplate>
        <DataTemplate x:DataType="local:Item">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition/>
                    <ColumnDefinition Width="Auto"/>
                </Grid.ColumnDefinitions>

                <TextBlock Text="{Binding Text}"/>

                <!-- x:Bind doesn't require visibility converter if min SDK is targeting Anniversary update -->
                <TextBlock Text="I'm selected!" Grid.Column="1" Visibility="{x:Bind IsSelected, Mode=OneWay}"/>
            </Grid>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

MainPage.xaml.cs

public sealed partial class MainPage : Page
{
    public MainPage()
    {
        this.InitializeComponent();
        DataContext = new MainPageViewModel();
    }
}

Screenshot

, , :

MainPageViewModel

public class MainPageViewModel : NotifyPropertyChangedBase
{
    public List<Item> Items { get; set; }

    public MainPageViewModel()
    {
        Items = new List<Item>()
        {
            new Item() { Text = "Apple" },
            new Item() { Text = "Banana" },
        };
    }

    public void SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        foreach (Item item in e.RemovedItems)
        {
            item.IsSelected = false;
        }

        foreach (Item item in e.AddedItems)
        {
            item.IsSelected = true;
        }
    }
}

MainPage.xaml

<ListView ItemsSource="{Binding Items}" SelectionChanged="{x:Bind ViewModel.SelectionChanged}" SelectionMode="Extended">
    <ListView.ItemContainerStyle>
        <Style TargetType="ListViewItem">
            <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
        </Style>
    </ListView.ItemContainerStyle>
    <ListView.ItemTemplate>
        <DataTemplate x:DataType="local:Item">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition/>
                    <ColumnDefinition Width="Auto"/>
                </Grid.ColumnDefinitions>

                <TextBlock Text="{Binding Text}"/>
                <TextBlock Text="I'm selected!" Grid.Column="1" Visibility="{x:Bind IsSelected, Mode=OneWay}"/>
            </Grid>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

MainPage.xaml.cs

public sealed partial class MainPage : Page
{
    public MainPage()
    {
        this.InitializeComponent();
        DataContext = new MainPageViewModel();
    }

    public MainPageViewModel ViewModel => (MainPageViewModel)DataContext;
}

Screenshot

+2

Source: https://habr.com/ru/post/1659320/


All Articles