7.4 KiB
AtomUI 6.1.1 API 变更示例
本文档补充 6.1.1 相比 6.1.0 的主要 API 变更和迁移写法。正式版本条目见仓库根目录
CHANGELOG.md 和 CHANGELOG.zh-CN.md。
ListView 选择模型迁移
6.1.1 将 ListView 选择状态改为内部稳定模型,并通过 IListViewSelection 暴露只读门面:
Selection从可设置的 AvaloniaISelectionModel变为只读IListViewSelection。SelectedItems从可设置的IList?变为只读IReadOnlyList<object?>。SelectedItem和SelectedValue变为只读快照。- 新增只读
SelectedIndexes。 - 新增
ItemKeySelector,用于按稳定业务 key 维护选择状态。 SelectionChanged事件参数从 AvaloniaSelectionChangedEventArgs变为ListViewSelectionChangedEventArgs。- 移除旧的
ListCollectionViewChangedEventArgs类型;6.1.1没有对应公开事件使用该类型。
直接设置选择模型
6.1.0 写法
var selection = new SelectionModel<object>
{
Source = customers
};
selection.Select(3);
listView.Selection = selection;
6.1.1 写法
listView.SelectedIndex = 3;
多选场景改为操作现有 Selection 门面:
listView.Selection.Clear();
foreach (var sourceIndex in selectedSourceIndexes)
{
listView.Selection.Select(sourceIndex);
}
绑定或设置 SelectedItems
6.1.0 写法
<atom:ListView
ItemsSource="{Binding Customers}"
SelectionMode="Multiple"
SelectedItems="{Binding SelectedCustomers, Mode=TwoWay}" />
6.1.1 写法
SelectedItems 现在是 ListView 的只读选择快照。需要把选择结果同步到 ViewModel 时,监听
SelectionChanged,并从控件当前快照读取完整选择:
<atom:ListView
x:Name="CustomersList"
ItemsSource="{Binding Customers}"
SelectionMode="Multiple"
SelectionChanged="HandleCustomersSelectionChanged" />
private void HandleCustomersSelectionChanged(object? sender, ListViewSelectionChangedEventArgs e)
{
if (sender is not ListView listView)
{
return;
}
SelectedCustomers.Clear();
foreach (var customer in listView.SelectedItems.OfType<Customer>())
{
SelectedCustomers.Add(customer);
}
}
需要从 ViewModel 状态回放选择时,按 source index 调用 Selection:
listView.Selection.Clear();
for (var index = 0; index < Customers.Count; index++)
{
if (selectedCustomerIds.Contains(Customers[index].Id))
{
listView.Selection.Select(index);
}
}
SelectionChanged 事件参数
6.1.0 写法
private void HandleSelectionChanged(object? sender, SelectionChangedEventArgs e)
{
foreach (var item in e.AddedItems)
{
AddSelection(item);
}
foreach (var item in e.RemovedItems)
{
RemoveSelection(item);
}
}
6.1.1 写法
private void HandleSelectionChanged(object? sender, ListViewSelectionChangedEventArgs e)
{
foreach (var item in e.SelectedItems)
{
AddSelection(item);
}
foreach (var item in e.DeselectedItems)
{
RemoveSelection(item);
}
}
如果需要索引,使用 SelectedIndexes 和 DeselectedIndexes:
private void HandleSelectionChanged(object? sender, ListViewSelectionChangedEventArgs e)
{
foreach (var sourceIndex in e.SelectedIndexes)
{
MarkSelected(sourceIndex);
}
foreach (var sourceIndex in e.DeselectedIndexes)
{
MarkDeselected(sourceIndex);
}
}
SelectedValue 回放
6.1.0 写法
<atom:ListView
ItemsSource="{Binding Customers}"
SelectedValueBinding="{Binding Id}"
SelectedValue="{Binding SelectedCustomerId, Mode=TwoWay}" />
6.1.1 写法
SelectedValue 现在跟随当前选择计算。需要写入选择值时,先在数据源中找到 source index,再设置
SelectedIndex:
<atom:ListView
x:Name="CustomersList"
ItemsSource="{Binding Customers}"
SelectedValueBinding="{Binding Id}"
SelectionChanged="HandleCustomerSelectionChanged" />
private void ApplySelectedCustomerId(EntityKey? selectedCustomerId)
{
CustomersList.SelectedIndex = selectedCustomerId is null
? -1
: FindCustomerSourceIndex(selectedCustomerId.Value);
}
private void HandleCustomerSelectionChanged(object? sender, ListViewSelectionChangedEventArgs e)
{
SelectedCustomerId = CustomersList.SelectedValue is EntityKey key ? key : null;
}
private int FindCustomerSourceIndex(EntityKey selectedCustomerId)
{
for (var index = 0; index < Customers.Count; index++)
{
if (Customers[index].Id == selectedCustomerId)
{
return index;
}
}
return -1;
}
稳定业务 key
如果同一个 item 会被过滤、分组、分页或重新投影,建议提供 ItemKeySelector。这样选择状态可以跟随业务
key,而不是依赖当前可见行位置:
CustomersList.ItemKeySelector = item => item switch
{
Customer customer => customer.Id,
IListItemData data => data.ItemKey,
_ => null
};
Select 和 Transfer 内部已迁移到新的 source index / item key 语义;自定义 ListView 派生控件也应优先
使用 Selection.IsSelected、Selection.Select 和 Selection.Deselect。
ListItemData 和 SelectOption 迁移
6.1.1 移除了 IListItemData.IsSelected / ListItemData.IsSelected。选择状态不再写在数据项上,而是由
ListView selection 模型维护。
同时,ListItemData、GroupListItemData 和 SelectOption 从 record 调整为 class。继承这些类型的代码
应从 record 改为 class,依赖 with 表达式复制的代码需要改为显式创建新实例。
数据项默认选中
6.1.0 写法
var item = new ListItemData
{
Content = customer,
ItemKey = customer.Id,
IsSelected = true
};
6.1.1 写法
var item = new ListItemData
{
Content = customer,
ItemKey = customer.Id
};
listView.Selection.Select(sourceIndex);
record 派生类型
6.1.0 写法
public record RichSelectOption : SelectOption
{
public string? Description { get; init; }
}
var next = option with
{
Header = "Updated"
};
6.1.1 写法
public class RichSelectOption : SelectOption
{
public string? Description { get; init; }
}
var next = new RichSelectOption
{
Header = "Updated",
Content = option.Content,
ItemKey = option.ItemKey,
Group = option.Group,
IsEnabled = option.IsEnabled,
Description = option.Description
};
WindowTitleBar 标题对齐
6.1.1 新增 WindowTitleBar.TitleAlignment 和 Window.TitleAlignment。默认 Auto 会按平台选择标题布局:
- macOS 默认使用
WindowCenter。 - Windows 和 Linux 默认使用
Left。
如果之前通过自定义 padding、margin 或 left/right add-on 宽度来调整标题位置,可以改为使用公开属性。
直接配置窗口标题
<atom:Window
Title="Settings"
TitleAlignment="WindowCenter">
<!-- window content -->
</atom:Window>
直接使用 WindowTitleBar
<atom:WindowTitleBar
Title="Settings"
TitleAlignment="Center"
LeftAddOn="{Binding Breadcrumb}"
RightAddOn="{Binding Actions}" />
Center 表示在标题栏可用内容区域内居中,WindowCenter 表示按物理窗口中心对齐。