11 KiB
AtomUI 6.1.0 API 变更示例
本文档补充 6.1.0 相比 6.0.8 的主要破坏性 API 变更和迁移写法。正式版本条目见仓库根目录
CHANGELOG.md 和 CHANGELOG.zh-CN.md。
Dialog 和 MessageBox 异步会话迁移
6.1.0 将 Dialog 和 MessageBox 的静态展示、关闭请求和宿主生命周期统一到异步 Session 模型:
- 移除同步静态 API:
ShowDialog、ShowDialogModal、ShowMessageBox。 - 移除带
closedcallback 的异步静态 API。 - 移除外部宿主扩展点:
IDialogHost、IDialogHostProvider。 - 移除结果包装接口:
IDialogActionResult、IMessageBoxActionResult。 - 静态 API 统一返回
Task<object?>,关闭结果直接从await结果获得。 - 关闭前校验统一使用
BeforeCloseAsync。
同步静态 Dialog 调用
6.0.8 写法
object? result = Dialog.ShowDialog<SettingsDialogView, SettingsDialogViewModel>(
viewModel,
new DialogOptions
{
Title = "Settings",
StandardButtons = DialogStandardButton.Ok | DialogStandardButton.Cancel
},
topLevel);
if (result is DialogCode.Accepted)
{
SaveSettings();
}
6.1.0 写法
object? result = await Dialog.ShowDialogAsync<SettingsDialogView, SettingsDialogViewModel>(
viewModel,
new DialogOptions
{
Title = "Settings",
StandardButtons = DialogStandardButton.Ok | DialogStandardButton.Cancel
},
topLevel);
if (result is DialogCode.Accepted)
{
SaveSettings();
}
callback 式 Dialog 关闭结果
6.0.8 写法
await Dialog.ShowDialogAsync(
new SettingsDialogView(),
viewModel,
new DialogOptions
{
Title = "Settings",
StandardButtons = DialogStandardButton.Ok | DialogStandardButton.Cancel
},
closed: actionResult =>
{
if (actionResult.Result is DialogCode.Accepted)
{
SaveSettings();
}
},
topLevel);
6.1.0 写法
object? result = await Dialog.ShowDialogAsync(
new SettingsDialogView(),
viewModel,
new DialogOptions
{
Title = "Settings",
StandardButtons = DialogStandardButton.Ok | DialogStandardButton.Cancel
},
topLevel);
if (result is DialogCode.Accepted)
{
SaveSettings();
}
实例 Dialog 打开
直接创建 Dialog 或 MessageBox 实例时,同步 Open() 也需要迁移到异步 OpenAsync()。关闭结果从实例的
Result 属性读取。
6.0.8 写法
var dialog = new Dialog
{
Title = "Settings",
Content = new SettingsDialogView(),
DataContext = viewModel,
StandardButtons = DialogStandardButton.Ok | DialogStandardButton.Cancel
};
object? result = dialog.Open();
if (result is DialogCode.Accepted)
{
SaveSettings();
}
6.1.0 写法
var dialog = new Dialog
{
Title = "Settings",
Content = new SettingsDialogView(),
DataContext = viewModel,
StandardButtons = DialogStandardButton.Ok | DialogStandardButton.Cancel
};
await dialog.OpenAsync();
object? result = dialog.Result;
if (result is DialogCode.Accepted)
{
SaveSettings();
}
MessageBox 静态 API 命名和结果
6.0.8 写法
await MessageBox.ShowMessageAsync(
new DeleteConfirmView(),
dataContext,
new MessageBoxOptions
{
Title = "Delete item",
Style = MessageBoxStyle.Confirm
},
closed: actionResult =>
{
if (actionResult.Result is DialogCode.Accepted)
{
DeleteItem();
}
},
topLevel);
6.1.0 写法
object? result = await MessageBox.ShowMessageBoxAsync(
new DeleteConfirmView(),
dataContext,
new MessageBoxOptions
{
Title = "Delete item",
Style = MessageBoxStyle.Confirm
},
topLevel);
if (result is DialogCode.Accepted)
{
DeleteItem();
}
模态 MessageBox 同样使用完整命名:
object? result = await MessageBox.ShowMessageBoxModalAsync(
new DeleteConfirmView(),
dataContext,
new MessageBoxOptions
{
Title = "Delete item",
Style = MessageBoxStyle.Warning
},
topLevel);
关闭前校验
BeforeCloseAsync 现在是 Dialog 和 MessageBox 关闭请求的统一校验入口。返回 false 表示拒绝本次关闭;
返回 true 表示允许关闭。
object? result = await Dialog.ShowDialogAsync(
new EditProfileView(),
viewModel,
new DialogOptions
{
Title = "Edit profile",
StandardButtons = DialogStandardButton.Ok | DialogStandardButton.Cancel,
BeforeCloseAsync = async context =>
{
if (context.DialogCode is DialogCode.Accepted)
{
return await viewModel.ValidateAndSaveAsync(context.CancellationToken);
}
return true;
}
},
topLevel);
自定义 Dialog 宿主
如果项目实现了 IDialogHost 或 IDialogHostProvider 来接管 overlay 宿主,6.1.0 不再支持这条扩展路径。
优先迁移到内置 host 选择和 placement 配置:
object? result = await Dialog.ShowDialogAsync(
new DetailsDialogView(),
viewModel,
new DialogOptions
{
DialogHostType = DialogHostType.Overlay,
PlacementTarget = ownerPanel,
HostWidth = 520,
HostMinHeight = 240
},
topLevel);
需要独立窗口宿主时显式选择 DialogHostType.Window:
object? result = await Dialog.ShowDialogModalAsync(
new ReportDialogView(),
viewModel,
new DialogOptions
{
DialogHostType = DialogHostType.Window,
Title = "Report"
},
topLevel);
Steps 受控状态迁移
6.1.0 将 Steps 从 SelectingItemsControl 改为 ItemsControl,公共状态围绕 Current、Initial、Status、
Percent、Type 和 TitlePlacement 表达。
API 对照
| 6.0.8 API | 6.1.0 API | 说明 |
|---|---|---|
CurrentStep |
Current |
当前步骤编号 |
InitialStep |
Initial |
第一个步骤的编号偏移 |
CurrentStepStatus |
Status |
当前步骤状态 |
StepsItemStatus |
StepsStatus |
状态枚举重命名 |
StepsStyle + StepsItemIndicatorType |
StepsType |
样式和指示器类型合并 |
LabelPlacement |
TitlePlacement |
标题布局位置 |
ProgressValue + IsShowItemProgress |
Percent |
可空进度值;null 表示不显示进度 |
SelectedIndex / SelectedItem |
Current + CurrentChangeRequested |
不再使用 Selection 状态 |
CurrentContent / CurrentContentTemplate |
业务 ViewModel 自行投影 | Steps 不再维护当前项内容出口 |
StepsItem.Description / DescriptionTemplate |
StepsItem.Content / ContentTemplate |
步骤详情改用标准 Content 契约 |
基础 XAML 属性迁移
6.0.8 写法
<atom:Steps
CurrentStep="{Binding CurrentStep}"
InitialStep="1"
CurrentStepStatus="Process"
Style="Default"
ItemIndicatorType="Dot"
LabelPlacement="Vertical"
IsShowItemProgress="True"
ProgressValue="{Binding ProgressValue}" />
6.1.0 写法
<atom:Steps
Current="{Binding CurrentStep}"
Initial="1"
Status="Process"
Type="Dot"
TitlePlacement="Vertical"
Percent="{Binding ProgressValue}" />
如果旧写法使用 Style="Navigation" 或 Style="Inline",直接迁移到 Type="Navigation" 或 Type="Inline"。
如果旧写法是默认样式加 ItemIndicatorType="Default",可以省略 Type 或写 Type="Default"。
可点击步骤
CurrentChangeRequested 是“用户请求切换步骤”的事件。控件不会在点击时直接修改 Current;业务代码确认允许
切换后,再更新绑定的 Current。
6.0.8 写法
<atom:Steps
CurrentStep="{Binding CurrentStep}"
IsItemClickable="True" />
6.1.0 写法
<atom:Steps
Current="{Binding CurrentStep}"
IsItemClickable="True"
CurrentChangeRequested="HandleCurrentChangeRequested" />
private void HandleCurrentChangeRequested(
object? sender,
StepsCurrentChangeRequestedEventArgs e)
{
if (ViewModel.CanMoveTo(e.Current))
{
ViewModel.CurrentStep = e.Current;
}
}
步骤项描述内容
6.0.8 写法
<atom:Steps>
<atom:StepsItem
Header="Login"
Description="Sign in with your account" />
<atom:StepsItem
Header="Verify"
Description="Enter the verification code" />
</atom:Steps>
6.1.0 写法
<atom:Steps>
<atom:StepsItem Header="Login">
Sign in with your account
</atom:StepsItem>
<atom:StepsItem Header="Verify">
Enter the verification code
</atom:StepsItem>
</atom:Steps>
复杂描述内容使用 ContentTemplate:
<atom:StepsItem Header="Verify" Content="{Binding VerifyStep}">
<atom:StepsItem.ContentTemplate>
<DataTemplate>
<atom:Space Orientation="Vertical" Spacing="4">
<TextBlock Text="{Binding Summary}" />
<TextBlock Text="{Binding HelpText}" />
</atom:Space>
</DataTemplate>
</atom:StepsItem.ContentTemplate>
</atom:StepsItem>
当前步骤内容投影
CurrentContent 和 CurrentContentTemplate 已移除。需要在 Steps 外部展示当前步骤页面时,由 ViewModel 根据
Current 投影当前内容。
6.0.8 写法
<atom:Steps
x:Name="WizardSteps"
CurrentStep="{Binding CurrentStep}"
ContentTemplate="{StaticResource WizardStepTemplate}" />
<ContentControl
Content="{Binding #WizardSteps.CurrentContent}"
ContentTemplate="{Binding #WizardSteps.CurrentContentTemplate}" />
6.1.0 写法
<atom:Steps
Current="{Binding CurrentStep}"
CurrentChangeRequested="HandleCurrentChangeRequested" />
<ContentControl
Content="{Binding CurrentStepContent}"
ContentTemplate="{StaticResource WizardStepTemplate}" />
public object? CurrentStepContent => Steps.FirstOrDefault(step => step.Number == CurrentStep);
private void HandleCurrentChangeRequested(
object? sender,
StepsCurrentChangeRequestedEventArgs e)
{
CurrentStep = e.Current;
RaisePropertyChanged(nameof(CurrentStepContent));
}
显式步骤状态
StepsItem.Status 现在是可空状态。未设置时使用 Steps 根据 Current、Initial 和根 Status 推导出的自动状态;
需要覆盖单个步骤时再显式设置:
<atom:Steps Current="{Binding CurrentStep}" Status="Process">
<atom:StepsItem Header="Create" />
<atom:StepsItem Header="Review" Status="Error" />
<atom:StepsItem Header="Publish" />
</atom:Steps>
这会只把 Review 固定为 Error,其他步骤继续使用自动状态。