launch page redo

This commit is contained in:
DismissedLight
2023-10-19 22:32:01 +08:00
parent 026c68229a
commit 91fea88623
11 changed files with 196 additions and 245 deletions

View File

@@ -1,48 +0,0 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using CommunityToolkit.WinUI.Behaviors;
using Microsoft.UI.Xaml;
namespace Snap.Hutao.Control.Behavior;
/// <summary>
/// 按给定比例自动调整高度的行为
/// </summary>
[HighQuality]
[DependencyProperty("TargetWidth", typeof(double), 1.0D)]
[DependencyProperty("TargetHeight", typeof(double), 1.0D)]
internal sealed partial class AutoHeightBehavior : BehaviorBase<FrameworkElement>
{
private readonly SizeChangedEventHandler sizeChangedEventHandler;
public AutoHeightBehavior()
{
sizeChangedEventHandler = OnSizeChanged;
}
/// <inheritdoc/>
protected override bool Initialize()
{
UpdateElement();
AssociatedObject.SizeChanged += sizeChangedEventHandler;
return true;
}
/// <inheritdoc/>
protected override bool Uninitialize()
{
AssociatedObject.SizeChanged -= sizeChangedEventHandler;
return true;
}
private void OnSizeChanged(object sender, SizeChangedEventArgs e)
{
UpdateElement();
}
private void UpdateElement()
{
AssociatedObject.Height = AssociatedObject.ActualWidth * (TargetHeight / TargetWidth);
}
}

View File

@@ -1,48 +0,0 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using CommunityToolkit.WinUI.Behaviors;
using Microsoft.UI.Xaml;
namespace Snap.Hutao.Control.Behavior;
/// <summary>
/// 按给定比例自动调整高度的行为
/// </summary>
[HighQuality]
[DependencyProperty("TargetWidth", typeof(double), 1.0D)]
[DependencyProperty("TargetHeight", typeof(double), 1.0D)]
internal sealed partial class AutoWidthBehavior : BehaviorBase<FrameworkElement>
{
private readonly SizeChangedEventHandler sizeChangedEventHandler;
public AutoWidthBehavior()
{
sizeChangedEventHandler = OnSizeChanged;
}
/// <inheritdoc/>
protected override bool Initialize()
{
UpdateElement();
AssociatedObject.SizeChanged += sizeChangedEventHandler;
return true;
}
/// <inheritdoc/>
protected override bool Uninitialize()
{
AssociatedObject.SizeChanged -= sizeChangedEventHandler;
return true;
}
private void OnSizeChanged(object sender, SizeChangedEventArgs e)
{
UpdateElement();
}
private void UpdateElement()
{
AssociatedObject.Width = AssociatedObject.Height * (TargetWidth / TargetHeight);
}
}

View File

@@ -16,7 +16,7 @@ internal sealed class RuntimeEnvironmentException : Exception
/// <param name="message">消息</param>
/// <param name="innerException">内部错误</param>
public RuntimeEnvironmentException(string message, Exception? innerException)
: base($"{message}\n{innerException.Message}", innerException)
: base($"{message}\n{innerException?.Message}", innerException)
{
}
}

View File

@@ -0,0 +1,14 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Microsoft.UI.Xaml;
namespace Snap.Hutao.Core.LifeCycle;
internal static class CurrentWindowReferenceExtension
{
public static XamlRoot GetXamlRoot(this ICurrentWindowReference reference)
{
return reference.Window.Content.XamlRoot;
}
}

View File

@@ -8,4 +8,4 @@ namespace Snap.Hutao.Core.LifeCycle;
internal interface ICurrentWindowReference
{
public Window Window { get; set; }
}
}

View File

@@ -23,7 +23,7 @@ internal sealed partial class ContentDialogFactory : IContentDialogFactory
await taskContext.SwitchToMainThreadAsync();
ContentDialog dialog = new()
{
XamlRoot = currentWindowReference.Window.Content.XamlRoot,
XamlRoot = currentWindowReference.GetXamlRoot(),
Title = title,
Content = content,
DefaultButton = ContentDialogButton.Primary,
@@ -39,7 +39,7 @@ internal sealed partial class ContentDialogFactory : IContentDialogFactory
await taskContext.SwitchToMainThreadAsync();
ContentDialog dialog = new()
{
XamlRoot = currentWindowReference.Window.Content.XamlRoot,
XamlRoot = currentWindowReference.GetXamlRoot(),
Title = title,
Content = content,
DefaultButton = defaultButton,
@@ -56,7 +56,7 @@ internal sealed partial class ContentDialogFactory : IContentDialogFactory
await taskContext.SwitchToMainThreadAsync();
ContentDialog dialog = new()
{
XamlRoot = currentWindowReference.Window.Content.XamlRoot,
XamlRoot = currentWindowReference.GetXamlRoot(),
Title = title,
Content = new ProgressBar() { IsIndeterminate = true },
};
@@ -69,7 +69,7 @@ internal sealed partial class ContentDialogFactory : IContentDialogFactory
{
await taskContext.SwitchToMainThreadAsync();
TContentDialog contentDialog = serviceProvider.CreateInstance<TContentDialog>(parameters);
contentDialog.XamlRoot = currentWindowReference.Window.Content.XamlRoot;
contentDialog.XamlRoot = currentWindowReference.GetXamlRoot();
return contentDialog;
}
@@ -77,7 +77,7 @@ internal sealed partial class ContentDialogFactory : IContentDialogFactory
where TContentDialog : ContentDialog
{
TContentDialog contentDialog = serviceProvider.CreateInstance<TContentDialog>(parameters);
contentDialog.XamlRoot = currentWindowReference.Window.Content.XamlRoot;
contentDialog.XamlRoot = currentWindowReference.GetXamlRoot();
return contentDialog;
}
}

View File

@@ -5190,6 +5190,24 @@ namespace Snap.Hutao.Resource.Localization {
}
}
/// <summary>
/// 查找类似 在游戏启动时修改其默认行为 的本地化字符串。
/// </summary>
internal static string ViewPageLaunchGameArgumentsDescription {
get {
return ResourceManager.GetString("ViewPageLaunchGameArgumentsDescription", resourceCulture);
}
}
/// <summary>
/// 查找类似 启动参数 的本地化字符串。
/// </summary>
internal static string ViewPageLaunchGameArgumentsHeader {
get {
return ResourceManager.GetString("ViewPageLaunchGameArgumentsHeader", resourceCulture);
}
}
/// <summary>
/// 查找类似 常规 的本地化字符串。
/// </summary>
@@ -5208,6 +5226,15 @@ namespace Snap.Hutao.Resource.Localization {
}
}
/// <summary>
/// 查找类似 文件 的本地化字符串。
/// </summary>
internal static string ViewPageLaunchGameFileHeader {
get {
return ResourceManager.GetString("ViewPageLaunchGameFileHeader", resourceCulture);
}
}
/// <summary>
/// 查找类似 在指定的显示器上运行 的本地化字符串。
/// </summary>
@@ -5253,6 +5280,24 @@ namespace Snap.Hutao.Resource.Localization {
}
}
/// <summary>
/// 查找类似 进程 的本地化字符串。
/// </summary>
internal static string ViewPageLaunchGameProcessHeader {
get {
return ResourceManager.GetString("ViewPageLaunchGameProcessHeader", resourceCulture);
}
}
/// <summary>
/// 查找类似 注册表 的本地化字符串。
/// </summary>
internal static string ViewPageLaunchGameRegistryHeader {
get {
return ResourceManager.GetString("ViewPageLaunchGameRegistryHeader", resourceCulture);
}
}
/// <summary>
/// 查找类似 增量包 的本地化字符串。
/// </summary>

View File

@@ -1883,12 +1883,21 @@
<data name="ViewPageLaunchGameAppearanceScreenWidthHeader" xml:space="preserve">
<value>宽度</value>
</data>
<data name="ViewPageLaunchGameArgumentsDescription" xml:space="preserve">
<value>在游戏启动时修改其默认行为</value>
</data>
<data name="ViewPageLaunchGameArgumentsHeader" xml:space="preserve">
<value>启动参数</value>
</data>
<data name="ViewPageLaunchGameCommonHeader" xml:space="preserve">
<value>常规</value>
</data>
<data name="ViewPageLaunchGameConfigurationSaveHint" xml:space="preserve">
<value>所有选项仅会在启动游戏成功后保存</value>
</data>
<data name="ViewPageLaunchGameFileHeader" xml:space="preserve">
<value>文件</value>
</data>
<data name="ViewPageLaunchGameMonitorsDescription" xml:space="preserve">
<value>在指定的显示器上运行</value>
</data>
@@ -1904,6 +1913,12 @@
<data name="ViewPageLaunchGameOptionsHeader" xml:space="preserve">
<value>游戏选项</value>
</data>
<data name="ViewPageLaunchGameProcessHeader" xml:space="preserve">
<value>进程</value>
</data>
<data name="ViewPageLaunchGameRegistryHeader" xml:space="preserve">
<value>注册表</value>
</data>
<data name="ViewPageLaunchGameResourceDiffHeader" xml:space="preserve">
<value>增量包</value>
</data>

View File

@@ -53,13 +53,7 @@ internal sealed class LaunchOptions : DbStoreOptions
public bool IsFullScreen
{
get => GetOption(ref isFullScreen, SettingEntry.LaunchIsFullScreen);
set
{
if (SetOption(ref isFullScreen, SettingEntry.LaunchIsFullScreen, value) && value)
{
IsBorderless = false;
}
}
set => SetOption(ref isFullScreen, SettingEntry.LaunchIsFullScreen, value);
}
/// <summary>
@@ -68,14 +62,7 @@ internal sealed class LaunchOptions : DbStoreOptions
public bool IsBorderless
{
get => GetOption(ref isBorderless, SettingEntry.LaunchIsBorderless);
set
{
if (SetOption(ref isBorderless, SettingEntry.LaunchIsBorderless, value) && value)
{
IsExclusive = false;
IsFullScreen = false;
}
}
set => SetOption(ref isBorderless, SettingEntry.LaunchIsBorderless, value);
}
/// <summary>
@@ -84,13 +71,7 @@ internal sealed class LaunchOptions : DbStoreOptions
public bool IsExclusive
{
get => GetOption(ref isExclusive, SettingEntry.LaunchIsExclusive);
set
{
if (SetOption(ref isExclusive, SettingEntry.LaunchIsExclusive, value) && value)
{
IsFullScreen = true;
}
}
set => SetOption(ref isExclusive, SettingEntry.LaunchIsExclusive, value);
}
/// <summary>
@@ -153,7 +134,7 @@ internal sealed class LaunchOptions : DbStoreOptions
private static void InitializeMonitors(List<NameValue<int>> monitors)
{
// This list can't use foreach
// https://github.com/microsoft/microsoft-ui-xaml/issues/6454
// https://github.com/microsoft/CsWinRT/issues/747
IReadOnlyList<DisplayArea> displayAreas = DisplayArea.FindAll();
for (int i = 0; i < displayAreas.Count; i++)
{
@@ -165,12 +146,15 @@ internal sealed class LaunchOptions : DbStoreOptions
private static void InitializeScreenFps(out int fps)
{
HDC hDC = GetDC(HWND.Null);
fps = GetDeviceCaps(hDC, GET_DEVICE_CAPS_INDEX.VREFRESH);
if (ReleaseDC(HWND.Null, hDC) == 0)
HDC hDC = default;
try
{
// not released
throw new Win32Exception();
hDC = GetDC(HWND.Null);
fps = GetDeviceCaps(hDC, GET_DEVICE_CAPS_INDEX.VREFRESH);
}
finally
{
_ = ReleaseDC(HWND.Null, hDC);
}
}
}

View File

@@ -68,7 +68,8 @@
IsOpen="True"
Message="{shcm:ResourceString Name=ViewPageLaunchGameConfigurationSaveHint}"
Severity="Informational"/>
<TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" Text="{shcm:ResourceString Name=ViewPageLaunchGameCommonHeader}"/>
<TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" Text="{shcm:ResourceString Name=ViewPageLaunchGameFileHeader}"/>
<cwc:SettingsCard
Header="{shcm:ResourceString Name=ViewPageLaunchGameSwitchSchemeHeader}"
HeaderIcon="{shcm:FontIcon Glyph=&#xE8AB;}"
@@ -93,6 +94,8 @@
Style="{StaticResource DefaultComboBoxStyle}"/>
</StackPanel>
</cwc:SettingsCard>
<TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" Text="{shcm:ResourceString Name=ViewPageLaunchGameRegistryHeader}"/>
<cwc:SettingsCard
ActionIconToolTip="{shcm:ResourceString Name=ViewPageLaunchGameSwitchAccountDetectAction}"
Command="{Binding DetectGameAccountCommand}"
@@ -182,81 +185,68 @@
</ListView>
</Border>
<TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" Text="{shcm:ResourceString Name=ViewPageLaunchGameAppearanceHeader}"/>
<cwc:SettingsCard
Description="{shcm:ResourceString Name=ViewPageLaunchGameAppearanceExclusiveDescription}"
Header="{shcm:ResourceString Name=ViewPageLaunchGameAppearanceExclusiveHeader}"
HeaderIcon="{shcm:FontIcon Glyph=&#xE740;}">
<ToggleSwitch Width="120" IsOn="{Binding Options.IsExclusive, Mode=TwoWay}"/>
</cwc:SettingsCard>
<cwc:SettingsCard
Description="{shcm:ResourceString Name=ViewPageLaunchGameAppearanceFullscreenDescription}"
Header="{shcm:ResourceString Name=ViewPageLaunchGameAppearanceFullscreenHeader}"
HeaderIcon="{shcm:FontIcon Glyph=&#xE740;}">
<ToggleSwitch Width="120" IsOn="{Binding Options.IsFullScreen, Mode=TwoWay}"/>
</cwc:SettingsCard>
<cwc:SettingsCard
Description="{shcm:ResourceString Name=ViewPageLaunchGameAppearanceBorderlessDescription}"
Header="{shcm:ResourceString Name=ViewPageLaunchGameAppearanceBorderlessHeader}"
HeaderIcon="{shcm:FontIcon Glyph=&#xE737;}">
<ToggleSwitch Width="120" IsOn="{Binding Options.IsBorderless, Mode=TwoWay}"/>
</cwc:SettingsCard>
<cwc:SettingsCard
Margin="0,6,0,0"
Description="{shcm:ResourceString Name=ViewPageLaunchGameAppearanceScreenWidthDescription}"
Header="{shcm:ResourceString Name=ViewPageLaunchGameAppearanceScreenWidthHeader}"
HeaderIcon="{shcm:FontIcon Glyph=&#xE76F;}">
<NumberBox
Width="156"
Padding="10,6,0,0"
Value="{Binding Options.ScreenWidth, Mode=TwoWay}"/>
</cwc:SettingsCard>
<cwc:SettingsCard
Description="{shcm:ResourceString Name=ViewPageLaunchGameAppearanceScreenHeightDescription}"
Header="{shcm:ResourceString Name=ViewPageLaunchGameAppearanceScreenHeightHeader}"
HeaderIcon="{shcm:FontIcon Glyph=&#xE784;}">
<NumberBox
Width="156"
Padding="10,6,0,0"
Value="{Binding Options.ScreenHeight, Mode=TwoWay}"/>
</cwc:SettingsCard>
<cwc:SettingsCard
Description="{shcm:ResourceString Name=ViewPageLaunchGameMonitorsDescription}"
Header="{shcm:ResourceString Name=ViewPageLaunchGameMonitorsHeader}"
HeaderIcon="{shcm:FontIcon Glyph=&#xE975;}">
<ComboBox
Width="156"
DisplayMemberPath="Name"
ItemsSource="{Binding Options.Monitors}"
SelectedItem="{Binding Options.Monitor, Mode=TwoWay}"/>
</cwc:SettingsCard>
<StackPanel Spacing="{StaticResource SettingsCardSpacing}" Visibility="{Binding AppOptions.IsAdvancedLaunchOptionsEnabled, Converter={StaticResource BoolToVisibilityConverter}}">
<TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" Text="{shcm:ResourceString Name=ViewPageLaunchGameAdvanceHeader}"/>
<cwc:SettingsCard
Description="{shcm:ResourceString Name=ViewPageLaunchGameUnlockFpsDescription}"
Header="{shcm:ResourceString Name=ViewPageLaunchGameUnlockFpsHeader}"
HeaderIcon="{shcm:FontIcon Glyph=&#xE785;}"
IsEnabled="{Binding HutaoOptions.IsElevated}">
<StackPanel Orientation="Horizontal">
<shvc:Elevation Margin="0,0,36,0" Visibility="{Binding HutaoOptions.IsElevated, Converter={StaticResource BoolToVisibilityRevertConverter}}"/>
<TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" Text="{shcm:ResourceString Name=ViewPageLaunchGameProcessHeader}"/>
<cwc:SettingsExpander
Description="{shcm:ResourceString Name=ViewPageLaunchGameArgumentsDescription}"
Header="{shcm:ResourceString Name=ViewPageLaunchGameArgumentsHeader}"
HeaderIcon="{shcm:FontIcon Glyph=&#xE943;}"
IsExpanded="True">
<cwc:SettingsExpander.Items>
<cwc:SettingsCard Description="{shcm:ResourceString Name=ViewPageLaunchGameAppearanceExclusiveDescription}" Header="-window-mode exclusive">
<ToggleSwitch Width="156" IsOn="{Binding Options.IsExclusive, Mode=TwoWay}"/>
</cwc:SettingsCard>
<cwc:SettingsCard Description="{shcm:ResourceString Name=ViewPageLaunchGameAppearanceFullscreenDescription}" Header="-screen-fullscreen">
<ToggleSwitch Width="156" IsOn="{Binding Options.IsFullScreen, Mode=TwoWay}"/>
</cwc:SettingsCard>
<cwc:SettingsCard Description="{shcm:ResourceString Name=ViewPageLaunchGameAppearanceBorderlessDescription}" Header="-popupwindow">
<ToggleSwitch Width="156" IsOn="{Binding Options.IsBorderless, Mode=TwoWay}"/>
</cwc:SettingsCard>
<cwc:SettingsCard Description="{shcm:ResourceString Name=ViewPageLaunchGameAppearanceScreenWidthDescription}" Header="-screen-width">
<NumberBox
MinWidth="156"
Padding="10,8,0,0"
Maximum="720"
Minimum="60"
SpinButtonPlacementMode="Inline"
Value="{Binding Options.TargetFps, Mode=TwoWay}"/>
<ToggleSwitch
Width="120"
IsOn="{Binding Options.UnlockFps, Mode=TwoWay}"
OffContent="{shcm:ResourceString Name=ViewPageLaunchGameUnlockFpsOff}"
OnContent="{shcm:ResourceString Name=ViewPageLaunchGameUnlockFpsOn}"/>
</StackPanel>
</cwc:SettingsCard>
</StackPanel>
Width="156"
Padding="10,6,0,0"
Value="{Binding Options.ScreenWidth, Mode=TwoWay}"/>
</cwc:SettingsCard>
<cwc:SettingsCard Description="{shcm:ResourceString Name=ViewPageLaunchGameAppearanceScreenHeightDescription}" Header="-screen-height">
<NumberBox
Width="156"
Padding="10,6,0,0"
Value="{Binding Options.ScreenHeight, Mode=TwoWay}"/>
</cwc:SettingsCard>
<cwc:SettingsCard Description="{shcm:ResourceString Name=ViewPageLaunchGameMonitorsDescription}" Header="-monitor">
<ComboBox
Width="156"
DisplayMemberPath="Name"
ItemsSource="{Binding Options.Monitors}"
SelectedItem="{Binding Options.Monitor, Mode=TwoWay}"/>
</cwc:SettingsCard>
</cwc:SettingsExpander.Items>
</cwc:SettingsExpander>
<cwc:SettingsCard
Description="{shcm:ResourceString Name=ViewPageLaunchGameUnlockFpsDescription}"
Header="{shcm:ResourceString Name=ViewPageLaunchGameUnlockFpsHeader}"
HeaderIcon="{shcm:FontIcon Glyph=&#xE785;}"
IsEnabled="{Binding HutaoOptions.IsElevated}"
Visibility="{Binding AppOptions.IsAdvancedLaunchOptionsEnabled, Converter={StaticResource BoolToVisibilityConverter}}">
<StackPanel Orientation="Horizontal">
<shvc:Elevation Margin="0,0,36,0" Visibility="{Binding HutaoOptions.IsElevated, Converter={StaticResource BoolToVisibilityRevertConverter}}"/>
<NumberBox
MinWidth="156"
Padding="10,8,0,0"
Maximum="720"
Minimum="60"
SpinButtonPlacementMode="Inline"
Value="{Binding Options.TargetFps, Mode=TwoWay}"/>
<ToggleSwitch
Width="120"
IsOn="{Binding Options.UnlockFps, Mode=TwoWay}"
OffContent="{shcm:ResourceString Name=ViewPageLaunchGameUnlockFpsOff}"
OnContent="{shcm:ResourceString Name=ViewPageLaunchGameUnlockFpsOn}"/>
</StackPanel>
</cwc:SettingsCard>
<StackPanel Spacing="{StaticResource SettingsCardSpacing}"/>
</StackPanel>
</Grid>
</ScrollViewer>

View File

@@ -126,49 +126,48 @@
<Border.Background>
<ImageBrush ImageSource="ms-appx:///Resource/Icon/UI_GachaShowPanel_Bg_Weapon.png"/>
</Border.Background>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<mxi:Interaction.Behaviors>
<shcb:AutoHeightBehavior TargetHeight="1024" TargetWidth="2048"/>
</mxi:Interaction.Behaviors>
<Border Grid.ColumnSpan="2" Background="{ThemeResource DarkOnlyOverlayMaskColorBrush}"/>
<ScrollViewer
Grid.Column="0"
Margin="16"
VerticalScrollBarVisibility="Hidden">
<StackPanel>
<shvc:BottomTextControl MaxWidth="80" Text="{shcm:ResourceString Name=ViewPageWiKiWeaponBeforeAscensionTitle}">
<shvc:ItemIcon Icon="{Binding Selected.Icon, Converter={StaticResource EquipIconConverter}}" Quality="{Binding Selected.RankLevel}"/>
</shvc:BottomTextControl>
<shvc:BottomTextControl Margin="0,16,0,0" Text="{shcm:ResourceString Name=ViewPageWiKiWeaponAfterAscensionTitle}">
<shvc:ItemIcon Icon="{Binding Selected.AwakenIcon, Converter={StaticResource EquipIconConverter}}" Quality="{Binding Selected.RankLevel}"/>
</shvc:BottomTextControl>
</StackPanel>
</ScrollViewer>
<Grid Grid.ColumnSpan="2">
<cwc:ConstrainedBox AspectRatio="2048:1024">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="176*"/>
<ColumnDefinition Width="848*"/>
<ColumnDefinition Width="auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<shci:CachedImage
<Border Grid.ColumnSpan="2" Background="{ThemeResource DarkOnlyOverlayMaskColorBrush}"/>
<ScrollViewer
Grid.Column="0"
Margin="16"
VerticalScrollBarVisibility="Hidden">
<StackPanel>
<shvc:BottomTextControl MaxWidth="80" Text="{shcm:ResourceString Name=ViewPageWiKiWeaponBeforeAscensionTitle}">
<shvc:ItemIcon Icon="{Binding Selected.Icon, Converter={StaticResource EquipIconConverter}}" Quality="{Binding Selected.RankLevel}"/>
</shvc:BottomTextControl>
<shvc:BottomTextControl Margin="0,16,0,0" Text="{shcm:ResourceString Name=ViewPageWiKiWeaponAfterAscensionTitle}">
<shvc:ItemIcon Icon="{Binding Selected.AwakenIcon, Converter={StaticResource EquipIconConverter}}" Quality="{Binding Selected.RankLevel}"/>
</shvc:BottomTextControl>
</StackPanel>
</ScrollViewer>
<Grid Grid.ColumnSpan="2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="176*"/>
<ColumnDefinition Width="848*"/>
</Grid.ColumnDefinitions>
<shci:CachedImage
Grid.Column="1"
HorizontalAlignment="Center"
VerticalAlignment="Stretch"
Source="{Binding Selected.Icon, Converter={StaticResource GachaEquipIconConverter}}"/>
</Grid>
<TextBlock
Grid.Column="1"
HorizontalAlignment="Center"
VerticalAlignment="Stretch"
Source="{Binding Selected.Icon, Converter={StaticResource GachaEquipIconConverter}}"/>
Margin="16"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
Style="{StaticResource SubtitleTextBlockStyle}"
Text="{Binding Selected.Name}"/>
</Grid>
<TextBlock
Grid.Column="1"
Margin="16"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
Style="{StaticResource SubtitleTextBlockStyle}"
Text="{Binding Selected.Name}"/>
</Grid>
</cwc:ConstrainedBox>
</Border>
</Border>