如何在Avalonia中绑定ListBoxItem.IsSelected到ViewModel属性?
在Avalonia中实现ListBoxItem.IsSelected与Item.IsSelected的双向绑定
我需要实现与Stack Overflow问题《How to bind ListBoxItem.IsSelected to boolean data property》相同的功能,但使用Avalonia而非WPF。
给定代码
ViewModel(MainViewModel.cs)
using System.Collections.Generic; using CommunityToolkit.Mvvm.ComponentModel; namespace AvaloniaAskOverflow.ViewModels; public partial class MainViewModel : ViewModelBase { private List<Item> items= new() { new ("Item 1", false), new ("Item 2", true), new ("Item 3", false), new ("Item 4", true) }; public List<Item> Items => items; } public class Item: ObservableObject { string text; public string Text { get => text; set => SetProperty(ref text, value); } bool isSelected; public bool IsSelected { get => isSelected; set => SetProperty(ref isSelected, value); } public Item(string text, bool isSelected) { this.text = text; this.isSelected = isSelected; } }
View代码(MainView.axaml)
<UserControl xmlns="https://github.com/avaloniaui" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:vm="clr-namespace:AvaloniaAskOverflow.ViewModels" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" x:Class="AvaloniaAskOverflow.Views.MainView" x:DataType="vm:MainViewModel"> <Design.DataContext> <!-- This only sets the DataContext for the previewer in an IDE, to set the actual DataContext for runtime, set the DataContext property in code (look at App.axaml.cs) --> <vm:MainViewModel /> </Design.DataContext> <ListBox SelectionMode="Multiple,Toggle" ItemsSource="{Binding Items}"> <ListBox.ItemTemplate> <DataTemplate> <TextBlock Text="{Binding Text}" /> </DataTemplate> </ListBox.ItemTemplate> <ListBox.ItemContainerTheme> <Style Selector="ListBoxItem"> <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" /> </Style> </ListBox.ItemContainerTheme> </ListBox> </UserControl>
说明:
- 保留注释以保证错误消息行号与代码一致。
- 与WPF解决方案的区别:Avalonia中没有
ListBox.ItemContainerStyle,等效为ListBox.ItemContainerTheme。
编译错误
Unable to resolve property or method of name 'IsSelected' on type 'AvaloniaAskOverflow.ViewModels.MainViewModel'. línea 24, posición 35.
程序试图在MainViewModel类中查找IsSelected属性,而非对应的Item实例的IsSelected属性。
解决方案
问题根源在于Avalonia中Style的绑定默认上下文是父级控件的DataContext(此处为MainViewModel),而非应用样式的ListBoxItem自身的DataContext(即Item实例)。需要明确指定绑定源为ListBoxItem的DataContext。
修改ListBox.ItemContainerTheme中的Style设置,使用$self引用ListBoxItem自身,绑定其DataContext下的IsSelected属性:
<ListBox.ItemContainerTheme> <Style Selector="ListBoxItem"> <Setter Property="IsSelected" Value="{Binding $self.DataContext.IsSelected, Mode=TwoWay}" /> </Style> </ListBox.ItemContainerTheme>
也可以使用RelativeSource的方式实现相同效果:
<ListBox.ItemContainerTheme> <Style Selector="ListBoxItem"> <Setter Property="IsSelected" Value="{Binding DataContext.IsSelected, Mode=TwoWay, RelativeSource={RelativeSource Self}}" /> </Style> </ListBox.ItemContainerTheme>
修改后,每个ListBoxItem的IsSelected属性会正确双向绑定到对应Item实例的IsSelected属性,实现预期功能。
内容的提问来源于stack exchange,提问作者Yanko Hernández Alvarez
相关产品推荐
相关产品推荐

