mirror of
https://github.com/wwiinnddyy/LanMountainDesktop.git
synced 2026-06-25 03:04:26 +08:00
fix.增强应用稳定性,修复了问题组件加载异常时连带应用崩溃的问题
This commit is contained in:
122
LanMountainDesktop.Tests/ComponentLibraryCrashRegressionTests.cs
Normal file
122
LanMountainDesktop.Tests/ComponentLibraryCrashRegressionTests.cs
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using LanMountainDesktop.Services;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace LanMountainDesktop.Tests;
|
||||||
|
|
||||||
|
public sealed class ComponentLibraryCrashRegressionTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void BuiltInComponentXaml_DoesNotAnimateRenderTransformDirectly()
|
||||||
|
{
|
||||||
|
var componentsDirectory = FindRepositoryPath("LanMountainDesktop", "Views", "Components");
|
||||||
|
foreach (var file in Directory.EnumerateFiles(componentsDirectory, "*.axaml", SearchOption.AllDirectories))
|
||||||
|
{
|
||||||
|
var xaml = File.ReadAllText(file);
|
||||||
|
foreach (Match match in Regex.Matches(
|
||||||
|
xaml,
|
||||||
|
@"<Style\.Animations>[\s\S]*?</Style\.Animations>",
|
||||||
|
RegexOptions.CultureInvariant))
|
||||||
|
{
|
||||||
|
Assert.DoesNotContain(
|
||||||
|
"Property=\"RenderTransform\"",
|
||||||
|
match.Value,
|
||||||
|
StringComparison.Ordinal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ComponentLibraryPreviewPages_FallBackWhenPreviewAttachFails()
|
||||||
|
{
|
||||||
|
var source = ReadRepositoryFile("LanMountainDesktop", "Views", "MainWindow.ComponentSystem.cs");
|
||||||
|
var buildSource = ExtractMethodSource(source, "BuildComponentLibraryComponentPages");
|
||||||
|
var pageSource = ExtractMethodSource(source, "CreateComponentLibraryComponentPage");
|
||||||
|
var contentSource = ExtractMethodSource(source, "CreateComponentLibraryComponentPageContent");
|
||||||
|
|
||||||
|
Assert.Contains("try", buildSource);
|
||||||
|
Assert.Contains("ComponentLibraryComponentPagesContainer.Children.Add(page)", buildSource);
|
||||||
|
Assert.Contains("forceFallback: true", buildSource);
|
||||||
|
Assert.Contains("UiExceptionGuard.IsFatalException", buildSource);
|
||||||
|
|
||||||
|
Assert.Contains("CreateStaticComponentPreviewFallback", contentSource);
|
||||||
|
Assert.Contains("forceFallback", pageSource);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void SoftwareRenderRetry_IsDisabledAfterAvaloniaLifetimeStarts()
|
||||||
|
{
|
||||||
|
var shouldRetry = Program.ShouldRetryWithSoftwareRendering(
|
||||||
|
AppRenderingModeHelper.Default,
|
||||||
|
new InvalidOperationException("render failed"),
|
||||||
|
isAvaloniaLifetimeStarted: true);
|
||||||
|
|
||||||
|
Assert.False(shouldRetry);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string ReadRepositoryFile(params string[] segments)
|
||||||
|
{
|
||||||
|
var path = FindRepositoryPath(segments);
|
||||||
|
return File.ReadAllText(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string FindRepositoryPath(params string[] segments)
|
||||||
|
{
|
||||||
|
var directory = new DirectoryInfo(AppContext.BaseDirectory);
|
||||||
|
while (directory is not null)
|
||||||
|
{
|
||||||
|
var candidate = Path.Combine(new[] { directory.FullName }.Concat(segments).ToArray());
|
||||||
|
if (File.Exists(candidate) || Directory.Exists(candidate))
|
||||||
|
{
|
||||||
|
return candidate;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (File.Exists(Path.Combine(directory.FullName, "LanMountainDesktop.slnx")))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
directory = directory.Parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new FileNotFoundException($"Could not locate repository path '{Path.Combine(segments)}'.");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string ExtractMethodSource(string source, string methodName)
|
||||||
|
{
|
||||||
|
var methodIndex = source.IndexOf($"private void {methodName}(", StringComparison.Ordinal);
|
||||||
|
if (methodIndex < 0)
|
||||||
|
{
|
||||||
|
methodIndex = source.IndexOf($"private Grid {methodName}(", StringComparison.Ordinal);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (methodIndex < 0)
|
||||||
|
{
|
||||||
|
methodIndex = source.IndexOf($"private StackPanel {methodName}(", StringComparison.Ordinal);
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.True(methodIndex >= 0, $"Could not locate method '{methodName}'.");
|
||||||
|
|
||||||
|
var braceIndex = source.IndexOf('{', methodIndex);
|
||||||
|
Assert.True(braceIndex >= 0, $"Could not locate method body for '{methodName}'.");
|
||||||
|
|
||||||
|
var depth = 0;
|
||||||
|
for (var i = braceIndex; i < source.Length; i++)
|
||||||
|
{
|
||||||
|
if (source[i] == '{')
|
||||||
|
{
|
||||||
|
depth++;
|
||||||
|
}
|
||||||
|
else if (source[i] == '}')
|
||||||
|
{
|
||||||
|
depth--;
|
||||||
|
if (depth == 0)
|
||||||
|
{
|
||||||
|
return source.Substring(methodIndex, i - methodIndex + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new InvalidOperationException($"Could not extract method '{methodName}'.");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -54,7 +54,7 @@ public sealed class Program
|
|||||||
WriteCrashDump(ex, StartupRenderMode);
|
WriteCrashDump(ex, StartupRenderMode);
|
||||||
|
|
||||||
// 渲染模式安全降级:若失败且未禁用重试,且当前不是软件渲染,则用软件渲染重试一次
|
// 渲染模式安全降级:若失败且未禁用重试,且当前不是软件渲染,则用软件渲染重试一次
|
||||||
if (ShouldRetryWithSoftwareRendering(StartupRenderMode, ex) &&
|
if (ShouldRetryWithSoftwareRendering(StartupRenderMode, ex, isAvaloniaLifetimeStarted: Application.Current is not null) &&
|
||||||
!attemptedRenderModes.Contains(AppRenderingModeHelper.Software))
|
!attemptedRenderModes.Contains(AppRenderingModeHelper.Software))
|
||||||
{
|
{
|
||||||
AppLogger.Warn("Startup", $"Retrying startup with Software rendering mode (previous='{StartupRenderMode}').");
|
AppLogger.Warn("Startup", $"Retrying startup with Software rendering mode (previous='{StartupRenderMode}').");
|
||||||
@@ -195,8 +195,16 @@ public sealed class Program
|
|||||||
/// 判断是否应该用软件渲染重试。当异常看起来与渲染相关(GPU/驱动/平台初始化),
|
/// 判断是否应该用软件渲染重试。当异常看起来与渲染相关(GPU/驱动/平台初始化),
|
||||||
/// 且当前渲染模式不是软件渲染,且未通过环境变量禁用重试时返回 true。
|
/// 且当前渲染模式不是软件渲染,且未通过环境变量禁用重试时返回 true。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private static bool ShouldRetryWithSoftwareRendering(string currentRenderMode, Exception ex)
|
internal static bool ShouldRetryWithSoftwareRendering(
|
||||||
|
string currentRenderMode,
|
||||||
|
Exception ex,
|
||||||
|
bool isAvaloniaLifetimeStarted = false)
|
||||||
{
|
{
|
||||||
|
if (isAvaloniaLifetimeStarted)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (string.Equals(currentRenderMode, AppRenderingModeHelper.Software, StringComparison.OrdinalIgnoreCase))
|
if (string.Equals(currentRenderMode, AppRenderingModeHelper.Software, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
<Setter Property="Foreground" Value="{DynamicResource AdaptiveTextPrimaryBrush}" />
|
<Setter Property="Foreground" Value="{DynamicResource AdaptiveTextPrimaryBrush}" />
|
||||||
<Setter Property="FontSize" Value="14" />
|
<Setter Property="FontSize" Value="14" />
|
||||||
<Setter Property="Padding" Value="16,10" />
|
<Setter Property="Padding" Value="16,10" />
|
||||||
|
<Setter Property="RenderTransform" Value="scale(1)" />
|
||||||
<Setter Property="Transitions">
|
<Setter Property="Transitions">
|
||||||
<Transitions>
|
<Transitions>
|
||||||
<TransformOperationsTransition Property="RenderTransform" Duration="{StaticResource FluttermotionToken.Duration.Fast}" />
|
<TransformOperationsTransition Property="RenderTransform" Duration="{StaticResource FluttermotionToken.Duration.Fast}" />
|
||||||
|
|||||||
@@ -150,6 +150,7 @@
|
|||||||
</Style>
|
</Style>
|
||||||
|
|
||||||
<Style Selector="ui|FANavigationViewItem.settings-nav-item">
|
<Style Selector="ui|FANavigationViewItem.settings-nav-item">
|
||||||
|
<Setter Property="RenderTransform" Value="scale(1)" />
|
||||||
<Setter Property="Transitions">
|
<Setter Property="Transitions">
|
||||||
<Transitions>
|
<Transitions>
|
||||||
<BrushTransition Property="Background" Duration="0:0:0.083" Easing="0.05,0.75,0.10,1.00" />
|
<BrushTransition Property="Background" Duration="0:0:0.083" Easing="0.05,0.75,0.10,1.00" />
|
||||||
|
|||||||
@@ -51,6 +51,7 @@
|
|||||||
<Setter Property="Padding" Value="12,6" />
|
<Setter Property="Padding" Value="12,6" />
|
||||||
<Setter Property="Margin" Value="0,0,8,8" />
|
<Setter Property="Margin" Value="0,0,8,8" />
|
||||||
<Setter Property="MinHeight" Value="34" />
|
<Setter Property="MinHeight" Value="34" />
|
||||||
|
<Setter Property="RenderTransform" Value="scale(1)" />
|
||||||
<Setter Property="Transitions">
|
<Setter Property="Transitions">
|
||||||
<Transitions>
|
<Transitions>
|
||||||
<BrushTransition Property="Background" Duration="{StaticResource FluttermotionToken.Duration.Standard}" Easing="0.05,0.75,0.10,1.00" />
|
<BrushTransition Property="Background" Duration="{StaticResource FluttermotionToken.Duration.Standard}" Easing="0.05,0.75,0.10,1.00" />
|
||||||
@@ -72,6 +73,7 @@
|
|||||||
</Style>
|
</Style>
|
||||||
|
|
||||||
<Style Selector=".settings-scope ComboBox">
|
<Style Selector=".settings-scope ComboBox">
|
||||||
|
<Setter Property="RenderTransform" Value="scale(1)" />
|
||||||
<Setter Property="Transitions">
|
<Setter Property="Transitions">
|
||||||
<Transitions>
|
<Transitions>
|
||||||
<BrushTransition Property="Background" Duration="{StaticResource FluttermotionToken.Duration.Fast}" Easing="0.05,0.75,0.10,1.00" />
|
<BrushTransition Property="Background" Duration="{StaticResource FluttermotionToken.Duration.Fast}" Easing="0.05,0.75,0.10,1.00" />
|
||||||
@@ -85,6 +87,7 @@
|
|||||||
</Style>
|
</Style>
|
||||||
|
|
||||||
<Style Selector=".settings-scope ToggleSwitch">
|
<Style Selector=".settings-scope ToggleSwitch">
|
||||||
|
<Setter Property="RenderTransform" Value="scale(1)" />
|
||||||
<Setter Property="Transitions">
|
<Setter Property="Transitions">
|
||||||
<Transitions>
|
<Transitions>
|
||||||
<DoubleTransition Property="Opacity" Duration="{StaticResource FluttermotionToken.Duration.Standard}" Easing="0.05,0.75,0.10,1.00" />
|
<DoubleTransition Property="Opacity" Duration="{StaticResource FluttermotionToken.Duration.Standard}" Easing="0.05,0.75,0.10,1.00" />
|
||||||
|
|||||||
@@ -48,7 +48,15 @@
|
|||||||
Background="{DynamicResource CardBackgroundSecondaryBrush}"
|
Background="{DynamicResource CardBackgroundSecondaryBrush}"
|
||||||
BorderBrush="Transparent"
|
BorderBrush="Transparent"
|
||||||
BorderThickness="0"
|
BorderThickness="0"
|
||||||
|
RenderTransform="scale(1)"
|
||||||
Cursor="Hand">
|
Cursor="Hand">
|
||||||
|
<Button.Transitions>
|
||||||
|
<Transitions>
|
||||||
|
<BrushTransition Property="Background" Duration="0:0:0.15" Easing="CubicEaseOut" />
|
||||||
|
<TransformOperationsTransition Property="RenderTransform" Duration="0:0:0.10" Easing="CubicEaseOut" />
|
||||||
|
</Transitions>
|
||||||
|
</Button.Transitions>
|
||||||
|
|
||||||
<StackPanel Orientation="Horizontal"
|
<StackPanel Orientation="Horizontal"
|
||||||
Spacing="6"
|
Spacing="6"
|
||||||
HorizontalAlignment="Center"
|
HorizontalAlignment="Center"
|
||||||
@@ -70,27 +78,13 @@
|
|||||||
<Button.Styles>
|
<Button.Styles>
|
||||||
<!-- 悬停状态 -->
|
<!-- 悬停状态 -->
|
||||||
<Style Selector="Button:pointerover">
|
<Style Selector="Button:pointerover">
|
||||||
<Style.Animations>
|
|
||||||
<Animation Duration="0:0:0.15" Easing="CubicEaseOut">
|
|
||||||
<KeyFrame Cue="100%">
|
|
||||||
<Setter Property="Background" Value="{DynamicResource CardBackgroundHoverBrush}"/>
|
<Setter Property="Background" Value="{DynamicResource CardBackgroundHoverBrush}"/>
|
||||||
</KeyFrame>
|
|
||||||
</Animation>
|
|
||||||
</Style.Animations>
|
|
||||||
</Style>
|
</Style>
|
||||||
|
|
||||||
<!-- 按下状态 -->
|
<!-- 按下状态 -->
|
||||||
<Style Selector="Button:pressed">
|
<Style Selector="Button:pressed">
|
||||||
<Style.Animations>
|
|
||||||
<Animation Duration="0:0:0.1" Easing="CubicEaseOut">
|
|
||||||
<KeyFrame Cue="100%">
|
|
||||||
<Setter Property="Background" Value="{DynamicResource CardBackgroundPressedBrush}"/>
|
<Setter Property="Background" Value="{DynamicResource CardBackgroundPressedBrush}"/>
|
||||||
<Setter Property="RenderTransform">
|
<Setter Property="RenderTransform" Value="scale(0.98)"/>
|
||||||
<ScaleTransform ScaleX="0.98" ScaleY="0.98"/>
|
|
||||||
</Setter>
|
|
||||||
</KeyFrame>
|
|
||||||
</Animation>
|
|
||||||
</Style.Animations>
|
|
||||||
</Style>
|
</Style>
|
||||||
</Button.Styles>
|
</Button.Styles>
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
@@ -3655,20 +3655,107 @@ public partial class MainWindow : Window
|
|||||||
for (var i = 0; i < componentCount; i++)
|
for (var i = 0; i < componentCount; i++)
|
||||||
{
|
{
|
||||||
var component = _componentLibraryActiveComponents[i];
|
var component = _componentLibraryActiveComponents[i];
|
||||||
|
|
||||||
var page = new Grid
|
|
||||||
{
|
|
||||||
Width = _componentLibraryComponentPageWidth,
|
|
||||||
Height = viewportHeight,
|
|
||||||
Background = Brushes.Transparent
|
|
||||||
};
|
|
||||||
|
|
||||||
// Fit the preview to the page while preserving component cell span proportions.
|
|
||||||
var previewMaxWidth = _componentLibraryComponentPageWidth * 0.94;
|
|
||||||
var previewMaxHeight = viewportHeight * 0.86;
|
|
||||||
var previewSpan = NormalizeComponentCellSpan(
|
var previewSpan = NormalizeComponentCellSpan(
|
||||||
component.ComponentId,
|
component.ComponentId,
|
||||||
(component.MinWidthCells, component.MinHeightCells));
|
(component.MinWidthCells, component.MinHeightCells));
|
||||||
|
var page = CreateComponentLibraryComponentPage(
|
||||||
|
component,
|
||||||
|
previewSpan,
|
||||||
|
_componentLibraryComponentPageWidth,
|
||||||
|
viewportHeight);
|
||||||
|
|
||||||
|
Grid.SetRow(page, 0);
|
||||||
|
Grid.SetColumn(page, i);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ComponentLibraryComponentPagesContainer.Children.Add(page);
|
||||||
|
}
|
||||||
|
catch (Exception ex) when (!UiExceptionGuard.IsFatalException(ex))
|
||||||
|
{
|
||||||
|
AppLogger.Warn(
|
||||||
|
"ComponentLibrary",
|
||||||
|
$"Failed to attach component library preview page for component '{component.ComponentId}'. Falling back to placeholder.",
|
||||||
|
ex);
|
||||||
|
|
||||||
|
DisposeStaticComponentLibraryPreviews([page]);
|
||||||
|
var fallbackPage = CreateComponentLibraryComponentPage(
|
||||||
|
component,
|
||||||
|
previewSpan,
|
||||||
|
_componentLibraryComponentPageWidth,
|
||||||
|
viewportHeight,
|
||||||
|
forceFallback: true);
|
||||||
|
Grid.SetRow(fallbackPage, 0);
|
||||||
|
Grid.SetColumn(fallbackPage, i);
|
||||||
|
ComponentLibraryComponentPagesContainer.Children.Add(fallbackPage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_componentLibraryComponentHostTransform = ComponentLibraryComponentPagesHost.RenderTransform as TranslateTransform;
|
||||||
|
if (_componentLibraryComponentHostTransform is null)
|
||||||
|
{
|
||||||
|
_componentLibraryComponentHostTransform = new TranslateTransform();
|
||||||
|
ComponentLibraryComponentPagesHost.RenderTransform = _componentLibraryComponentHostTransform;
|
||||||
|
}
|
||||||
|
|
||||||
|
ApplyComponentLibraryComponentOffset();
|
||||||
|
UpdateComponentLibraryComponentNavigationButtons();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Grid CreateComponentLibraryComponentPage(
|
||||||
|
ComponentLibraryComponentEntry component,
|
||||||
|
(int WidthCells, int HeightCells) previewSpan,
|
||||||
|
double pageWidth,
|
||||||
|
double pageHeight,
|
||||||
|
bool forceFallback = false)
|
||||||
|
{
|
||||||
|
var page = new Grid
|
||||||
|
{
|
||||||
|
Width = pageWidth,
|
||||||
|
Height = pageHeight,
|
||||||
|
Background = Brushes.Transparent
|
||||||
|
};
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var stack = CreateComponentLibraryComponentPageContent(
|
||||||
|
component,
|
||||||
|
previewSpan,
|
||||||
|
pageWidth,
|
||||||
|
pageHeight,
|
||||||
|
forceFallback);
|
||||||
|
page.Children.Add(stack);
|
||||||
|
}
|
||||||
|
catch (Exception ex) when (!UiExceptionGuard.IsFatalException(ex) && !forceFallback)
|
||||||
|
{
|
||||||
|
AppLogger.Warn(
|
||||||
|
"ComponentLibrary",
|
||||||
|
$"Failed to build component library preview page for component '{component.ComponentId}'. Falling back to placeholder.",
|
||||||
|
ex);
|
||||||
|
|
||||||
|
page.Children.Clear();
|
||||||
|
var stack = CreateComponentLibraryComponentPageContent(
|
||||||
|
component,
|
||||||
|
previewSpan,
|
||||||
|
pageWidth,
|
||||||
|
pageHeight,
|
||||||
|
forceFallback: true);
|
||||||
|
page.Children.Add(stack);
|
||||||
|
}
|
||||||
|
|
||||||
|
return page;
|
||||||
|
}
|
||||||
|
|
||||||
|
private StackPanel CreateComponentLibraryComponentPageContent(
|
||||||
|
ComponentLibraryComponentEntry component,
|
||||||
|
(int WidthCells, int HeightCells) previewSpan,
|
||||||
|
double pageWidth,
|
||||||
|
double pageHeight,
|
||||||
|
bool forceFallback)
|
||||||
|
{
|
||||||
|
// Fit the preview to the page while preserving component cell span proportions.
|
||||||
|
var previewMaxWidth = pageWidth * 0.94;
|
||||||
|
var previewMaxHeight = pageHeight * 0.86;
|
||||||
var previewCellSize = Math.Min(
|
var previewCellSize = Math.Min(
|
||||||
previewMaxWidth / Math.Max(1, previewSpan.WidthCells),
|
previewMaxWidth / Math.Max(1, previewSpan.WidthCells),
|
||||||
previewMaxHeight / Math.Max(1, previewSpan.HeightCells));
|
previewMaxHeight / Math.Max(1, previewSpan.HeightCells));
|
||||||
@@ -3676,7 +3763,9 @@ public partial class MainWindow : Window
|
|||||||
|
|
||||||
var previewWidth = previewSpan.WidthCells * previewCellSize;
|
var previewWidth = previewSpan.WidthCells * previewCellSize;
|
||||||
var previewHeight = previewSpan.HeightCells * previewCellSize;
|
var previewHeight = previewSpan.HeightCells * previewCellSize;
|
||||||
var previewControl = CreateStaticComponentLibraryPreview(
|
var previewControl = forceFallback
|
||||||
|
? CreateStaticComponentPreviewFallback(previewWidth, previewHeight)
|
||||||
|
: CreateStaticComponentLibraryPreview(
|
||||||
component.ComponentId,
|
component.ComponentId,
|
||||||
previewCellSize,
|
previewCellSize,
|
||||||
previewWidth,
|
previewWidth,
|
||||||
@@ -3721,7 +3810,7 @@ public partial class MainWindow : Window
|
|||||||
HorizontalAlignment = HorizontalAlignment.Center
|
HorizontalAlignment = HorizontalAlignment.Center
|
||||||
};
|
};
|
||||||
|
|
||||||
var stack = new StackPanel
|
return new StackPanel
|
||||||
{
|
{
|
||||||
Spacing = 8,
|
Spacing = 8,
|
||||||
HorizontalAlignment = HorizontalAlignment.Center,
|
HorizontalAlignment = HorizontalAlignment.Center,
|
||||||
@@ -3733,23 +3822,6 @@ public partial class MainWindow : Window
|
|||||||
hint
|
hint
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
page.Children.Add(stack);
|
|
||||||
|
|
||||||
Grid.SetRow(page, 0);
|
|
||||||
Grid.SetColumn(page, i);
|
|
||||||
ComponentLibraryComponentPagesContainer.Children.Add(page);
|
|
||||||
}
|
|
||||||
|
|
||||||
_componentLibraryComponentHostTransform = ComponentLibraryComponentPagesHost.RenderTransform as TranslateTransform;
|
|
||||||
if (_componentLibraryComponentHostTransform is null)
|
|
||||||
{
|
|
||||||
_componentLibraryComponentHostTransform = new TranslateTransform();
|
|
||||||
ComponentLibraryComponentPagesHost.RenderTransform = _componentLibraryComponentHostTransform;
|
|
||||||
}
|
|
||||||
|
|
||||||
ApplyComponentLibraryComponentOffset();
|
|
||||||
UpdateComponentLibraryComponentNavigationButtons();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ClearComponentLibraryPreviewControls()
|
private void ClearComponentLibraryPreviewControls()
|
||||||
|
|||||||
@@ -76,6 +76,7 @@
|
|||||||
<Setter Property="HorizontalAlignment" Value="Stretch" />
|
<Setter Property="HorizontalAlignment" Value="Stretch" />
|
||||||
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
|
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
|
||||||
<Setter Property="MinHeight" Value="48" />
|
<Setter Property="MinHeight" Value="48" />
|
||||||
|
<Setter Property="RenderTransform" Value="scale(1)" />
|
||||||
<Setter Property="Transitions">
|
<Setter Property="Transitions">
|
||||||
<Transitions>
|
<Transitions>
|
||||||
<BrushTransition Property="Background" Duration="{StaticResource FluttermotionToken.Duration.Fast}" />
|
<BrushTransition Property="Background" Duration="{StaticResource FluttermotionToken.Duration.Fast}" />
|
||||||
|
|||||||
Reference in New Issue
Block a user