6.5 KiB
Dialog 自定义样式指南
Dialog 的视觉表现通过 ControlTheme + Design Token 系统控制。由于 Dialog 的特殊架构(内容代理给宿主渲染),样式自定义主要通过控件属性和事件回调实现。
1. 使用属性直接控制
最简单的方式是通过 Dialog 的公共属性来控制外观和行为:
<!-- 基础模态对话框 -->
<atom:Dialog Title="Basic Modal"
IsModal="True"
StandardButtons="Ok, Cancel"
DefaultStandardButton="Ok"
MinWidth="300">
<TextBlock>Some contents...</TextBlock>
</atom:Dialog>
<!-- 居中显示 -->
<atom:Dialog Title="Centered Modal"
HorizontalStartupLocation="Center"
VerticalStartupLocation="Center" />
<!-- 百分比偏移定位 -->
<atom:Dialog Title="Offset Modal"
HorizontalStartupLocation="Center"
VerticalOffset="30%" />
<!-- 可拖拽对话框 -->
<atom:Dialog Title="Draggable"
IsDragMovable="True" />
<!-- 窗口宿主模式 -->
<atom:Dialog Title="Window Modal"
DialogHostType="Window"
IsClosable="True"
IsMaximizable="False" />
<!-- 隐藏底部按钮 -->
<atom:Dialog Title="No Footer"
IsFooterVisible="False" />
<!-- 点击遮罩关闭 -->
<atom:Dialog Title="Light Dismiss"
IsLightDismissEnabled="True" />
📖 完整示例参考:
controlgallery/AtomUIGallery/ShowCases/Views/Feedback/ModalShowCase.axaml
2. 自定义底部按钮
标准按钮配置
通过 StandardButtons 属性指定标准按钮组合:
<!-- Ok + Cancel -->
<atom:Dialog StandardButtons="Ok, Cancel" DefaultStandardButton="Ok" />
<!-- Yes + No -->
<atom:Dialog StandardButtons="Yes, No" DefaultStandardButton="Yes" />
<!-- 仅 Reload 按钮 -->
<atom:Dialog StandardButtons="Reload" DefaultStandardButton="Reload" />
添加自定义按钮
通过 CustomButtons 集合添加额外按钮:
<atom:Dialog StandardButtons="Ok, Cancel"
DefaultStandardButton="Ok">
<atom:Dialog.CustomButtons>
<atom:DialogButton Role="ActionRole">Custom Button</atom:DialogButton>
</atom:Dialog.CustomButtons>
<TextBlock>Content with custom button</TextBlock>
</atom:Dialog>
通过回调配置按钮属性
使用 ButtonsConfigure 回调在按钮创建后统一修改属性:
// Code-behind
dialog.ButtonsConfigure = buttons =>
{
foreach (var button in buttons)
{
button.IsEnabled = false; // 禁用所有按钮
}
};
📖 参考:
controlgallery/AtomUIGallery/ShowCases/Views/Feedback/ModalShowCase.axaml中 "Customize footer buttons props" 示例。
3. 异步关闭模式
通过 ButtonClicked 事件拦截按钮点击,实现异步关闭:
<atom:Dialog StandardButtons="Ok, Cancel"
ButtonClicked="HandleDialogButtonClicked" />
private void HandleDialogButtonClicked(object? sender, DialogButtonClickedEventArgs e)
{
if (sender is Dialog dialog && e.SourceButton.Role == DialogButtonRole.AcceptRole)
{
dialog.IsConfirmLoading = true;
e.Handled = true; // 阻止默认关闭行为
DispatcherTimer.RunOnce(() =>
{
dialog.IsConfirmLoading = false;
dialog.Done(); // 手动关闭
}, TimeSpan.FromMilliseconds(3000));
}
}
📖 参考:
controlgallery/AtomUIGallery/ShowCases/Views/Feedback/ModalShowCase.axaml中 "Asynchronously close" 示例。
4. 加载状态
<!-- 整体加载状态 -->
<atom:Dialog IsLoading="True" StandardButtons="Reload">
<TextBlock>Loading content...</TextBlock>
</atom:Dialog>
// 打开后自动结束加载
private void HandleDialogOpened(object? sender, EventArgs e)
{
if (sender is Dialog dialog)
{
DispatcherTimer.RunOnce(() =>
{
dialog.IsLoading = false;
}, TimeSpan.FromMilliseconds(3000));
}
}
📖 参考:
controlgallery/AtomUIGallery/ShowCases/Views/Feedback/ModalShowCase.axaml中 "Loading" 示例。
5. 静态 API 创建对话框
// Overlay 模态对话框
var options = new DialogOptions
{
Title = "Basic Modal",
IsResizable = false,
IsDragMovable = true,
StandardButtons = DialogStandardButtons.Parse("Cancel,Ok"),
DefaultStandardButton = DialogStandardButton.Ok,
HorizontalStartupLocation = DialogHorizontalAnchor.Center,
VerticalOffset = new Dimension(30, DimensionUnitType.Percentage),
MinWidth = 400
};
var result = await Dialog.ShowDialogModalAsync(content, null, options);
// Window 模态对话框
var windowOptions = new DialogOptions
{
Title = "Window Modal",
DialogHostType = DialogHostType.Window,
// ...其他选项同上
};
await Dialog.ShowDialogModalAsync(content, null, windowOptions);
// 泛型视图 + ViewModel
await Dialog.ShowDialogModalAsync<MyView, MyViewModel>(viewModel, options);
📖 参考:
controlgallery/AtomUIGallery/ShowCases/Views/Feedback/ModalShowCase.axaml.cs中 "Static Dialog API" 示例。
6. 使用 Closing 事件阻止关闭
通过 Closing 事件可以在对话框关闭前进行验证,设置 Cancel = true 阻止关闭:
dialog.Closing += (sender, e) =>
{
// 例如:校验表单是否已保存
if (!IsFormSaved)
{
e.Cancel = true; // 阻止关闭
}
};
注意:当
IsConfirmLoading = true时,NotifyClose()方法会直接返回,不触发Closing事件。这是一个更强的关闭保护机制。
样式选择器速查
说明:由于 Dialog 将内容代理给
OverlayDialogHost或DialogHost渲染,样式选择器应针对宿主类型使用。
按控件类型选择
| 选择器 | 说明 |
|---|---|
atom|Dialog |
匹配 Dialog 控件本身(但 Dialog 不渲染可视内容) |
atom|OverlayDialogHost |
匹配 Overlay 模式的对话框宿主 |
atom|DialogHost |
匹配 Window 模式的对话框宿主 |
内部元素选择
| 选择器 | 说明 |
|---|---|
atom|OverlayDialogHost /template/ atom|OverlayDialogHeader#PART_Header |
Overlay 对话框标题栏 |
atom|OverlayDialogHost /template/ atom|OverlayDialogResizer#PART_Resizer |
Overlay 对话框调整大小控件 |
atom|OverlayDialogHost /template/ atom|DialogButtonBox#PART_ButtonBox |
Overlay 对话框按钮区域 |
atom|OverlayDialogHost /template/ atom|OverlayDialogMask |
Overlay 对话框遮罩层 |