XAML 如何在ListViewItem的DataTemplate中绑定IsSelected属性

e37o9pze  于 2022-12-07  发布在  其他
关注(0)|答案(3)|浏览(187)

我想把ListViewItem写在UWP里,这会改变他对选择的看法,所以我需要改变ListViewItem的一些元素的Visibility属性。
我找到了一些方法来实现这一点,方法是为ListViewItem创建自定义样式并绑定IsSelected属性,如下所示:

<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>

它的工作很好,但与这种方式,我不能绑定的DeviceID文本。
另一种方法是创建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>

现在我可以正确绑定文本,但是不能绑定IsSelected属性。我已经尝试过用不同的模式来绑定,但是仍然不起作用,因为我不能在DataTemplate中使用TemplatedParent键。
所以我需要一些答案:

  • 我可以用第一种方式绑定文本吗?我该怎么做?-我该怎么用第二种方式绑定IsSelected属性?
fdx2calv

fdx2calv1#

我不建议更改ListViewItem模板,因为您会失去它提供的所有功能(选择外观、检查能力等)。
在第二个代码段中使用Mode=TemplatedParent将不起作用,因为该上下文中的模板化父项是ListViewItemPresenter,而不是ListViewItem(表示者的父项)。
看起来您尝试做的是在选中列表项时在其中显示附加信息。

单选

    • C#类别**
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" },
        };
    }
}
    • 主页面. 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>
    • 主页面. xaml. cs**
public sealed partial class MainPage : Page
{
    public MainPage()
    {
        this.InitializeComponent();
        DataContext = new 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;
        }
    }
}
    • 主页面. 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>
    • 主页面. xaml. cs**
public sealed partial class MainPage : Page
{
    public MainPage()
    {
        this.InitializeComponent();
        DataContext = new MainPageViewModel();
    }

    public MainPageViewModel ViewModel => (MainPageViewModel)DataContext;
}

voase2hg

voase2hg2#

若要回答主题中的实际问题:是的,您可以很容易地绑定ListViewItem.IsSelected。请确保您的DataTemplate内容 Package 在ListViewItem中。

<ListView.ItemTemplate>
    <DataTemplate x:DataType="local:MyItemViewModel">
        <ListViewItem IsSelected="{Binding IsSelected, Mode=TwoWay}">
            <Grid>
                // template content
            </Grid>
        </ListViewItem>
    </DataTemplate>
</ListView.ItemTemplate>

请注意,这里有许多关于WPF的问答都说这不起作用。它可以与UWP一起工作(至少在SDK 10.0.19041中)。WPF的回答建议将它绑定到ItemsPanelTemplate或ResourceDictionary中。由于某种原因,这在UWP中不起作用。

bjp0bcyl

bjp0bcyl3#

我执行了以下操作,效果很好

<ListView.ItemTemplate>
    <DataTemplate x:DataType="local:PersonalProfile">
        <ListViewItem x:Name="root">
             <Grid >
             <!-- .... -->
                 <CheckBox IsChecked="{Binding ElementName=root, Path=IsSelected, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
             </Grid>
        </ListViewItem>
    </DataTemplate>
</ListView.ItemTemplate>

相关问题