You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 22:02:09