From 14f7f240be76a1d7506dc5d909b4317b9075a1ad Mon Sep 17 00:00:00 2001 From: Ionite Date: Tue, 22 Aug 2023 23:54:46 -0400 Subject: [PATCH] Add upscale option and fix GAN upscales --- .../Controls/ImageGalleryCard.axaml | 8 + .../Controls/SamplerCard.axaml | 51 +-- .../DesignData/DesignData.cs | 6 +- .../Inference/ImageGalleryCardViewModel.cs | 37 +- .../InferenceTextToImageViewModel.cs | 368 ++++++++++-------- .../Inference/StackExpanderViewModel.cs | 12 +- .../ViewModels/SettingsViewModel.cs | 7 +- .../Views/Dialogs/ImageViewerDialog.axaml | 23 +- .../Api/Comfy/Nodes/ComfyNodeBuilder.cs | 168 +++++++- 9 files changed, 480 insertions(+), 200 deletions(-) diff --git a/StabilityMatrix.Avalonia/Controls/ImageGalleryCard.axaml b/StabilityMatrix.Avalonia/Controls/ImageGalleryCard.axaml index a1383339..9ccb02e9 100644 --- a/StabilityMatrix.Avalonia/Controls/ImageGalleryCard.axaml +++ b/StabilityMatrix.Avalonia/Controls/ImageGalleryCard.axaml @@ -65,11 +65,19 @@ StretchDirection="Both"> + + diff --git a/StabilityMatrix.Avalonia/Controls/SamplerCard.axaml b/StabilityMatrix.Avalonia/Controls/SamplerCard.axaml index 6503cff0..95706239 100644 --- a/StabilityMatrix.Avalonia/Controls/SamplerCard.axaml +++ b/StabilityMatrix.Avalonia/Controls/SamplerCard.axaml @@ -6,7 +6,7 @@ x:DataType="vmInference:SamplerCardViewModel" xmlns:mocks="clr-namespace:StabilityMatrix.Avalonia.DesignData"> - + @@ -21,7 +21,7 @@ + Spacing="12"> - - - - - - - + + + - - + HorizontalAlignment="Stretch" + MinWidth="70" + SpinButtonPlacementMode="Compact"/> + + + DialogFactory.Get(); + => DialogFactory.Get(vm => + { + vm.Source = + "https://image.civitai.com/xG1nkqKTMzGDvpLrqFT7WA/a318ac1f-3ad0-48ac-98cc-79126febcc17/width=1024"; + }); public static Indexer Types => new(); diff --git a/StabilityMatrix.Avalonia/ViewModels/Inference/ImageGalleryCardViewModel.cs b/StabilityMatrix.Avalonia/ViewModels/Inference/ImageGalleryCardViewModel.cs index 12abe23e..bda635aa 100644 --- a/StabilityMatrix.Avalonia/ViewModels/Inference/ImageGalleryCardViewModel.cs +++ b/StabilityMatrix.Avalonia/ViewModels/Inference/ImageGalleryCardViewModel.cs @@ -11,7 +11,10 @@ using NLog; using StabilityMatrix.Avalonia.Controls; using StabilityMatrix.Avalonia.Helpers; using StabilityMatrix.Avalonia.Models; +using StabilityMatrix.Avalonia.Services; using StabilityMatrix.Avalonia.ViewModels.Base; +using StabilityMatrix.Avalonia.ViewModels.Dialogs; +using StabilityMatrix.Avalonia.Views.Dialogs; using StabilityMatrix.Core.Attributes; using StabilityMatrix.Core.Helper; @@ -21,7 +24,8 @@ namespace StabilityMatrix.Avalonia.ViewModels.Inference; public partial class ImageGalleryCardViewModel : ViewModelBase { private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); - + private readonly ServiceManager vmFactory; + [ObservableProperty] private bool isPreviewOverlayEnabled; @@ -41,8 +45,10 @@ public partial class ImageGalleryCardViewModel : ViewModelBase public bool CanNavigateBack => SelectedImageIndex > 0; public bool CanNavigateForward => SelectedImageIndex < ImageSources.Count - 1; - public ImageGalleryCardViewModel() + public ImageGalleryCardViewModel(ServiceManager vmFactory) { + this.vmFactory = vmFactory; + ImageSources.CollectionChanged += OnImageSourcesItemsChanged; } @@ -82,7 +88,7 @@ public partial class ImageGalleryCardViewModel : ViewModelBase return; } - Logger.Trace($"FlyoutCopy is copying {image}"); + Logger.Trace($"FlyoutCopy is copying bitmap..."); await Task.Run(() => { @@ -92,4 +98,29 @@ public partial class ImageGalleryCardViewModel : ViewModelBase } }); } + + [RelayCommand] + // ReSharper disable once UnusedMember.Local + private async Task FlyoutPreview(IImage? image) + { + if (image is null) + { + Logger.Trace("FlyoutPreview: image is null"); + return; + } + + Logger.Trace($"FlyoutPreview opening..."); + + var viewerVm = vmFactory.Get(); + viewerVm.Image = (Bitmap) image; + + var dialog = new BetterContentDialog + { + Content = new ImageViewerDialog + { + DataContext = viewerVm, + } + }; + + } } diff --git a/StabilityMatrix.Avalonia/ViewModels/Inference/InferenceTextToImageViewModel.cs b/StabilityMatrix.Avalonia/ViewModels/Inference/InferenceTextToImageViewModel.cs index 0338333a..88acb1c2 100644 --- a/StabilityMatrix.Avalonia/ViewModels/Inference/InferenceTextToImageViewModel.cs +++ b/StabilityMatrix.Avalonia/ViewModels/Inference/InferenceTextToImageViewModel.cs @@ -43,22 +43,20 @@ public partial class InferenceTextToImageViewModel : InferenceTabViewModelBase private readonly ServiceManager vmFactory; public IInferenceClientManager ClientManager { get; } - + public ImageGalleryCardViewModel ImageGalleryCardViewModel { get; } public PromptCardViewModel PromptCardViewModel { get; } public StackCardViewModel StackCardViewModel { get; } - public UpscalerCardViewModel UpscalerCardViewModel => - StackCardViewModel - .GetCard() - .GetCard(); + public UpscalerCardViewModel UpscalerCardViewModel => + StackCardViewModel.GetCard().GetCard(); public SamplerCardViewModel HiresSamplerCardViewModel => - StackCardViewModel - .GetCard() - .GetCard(); + StackCardViewModel.GetCard().GetCard(); public bool IsHiresFixEnabled => StackCardViewModel.GetCard().IsEnabled; + + public bool IsUpscaleEnabled => StackCardViewModel.GetCard(1).IsEnabled; [JsonIgnore] public ProgressViewModel OutputProgress { get; } = new(); @@ -78,44 +76,58 @@ public partial class InferenceTextToImageViewModel : InferenceTabViewModelBase ClientManager = inferenceClientManager; // Get sub view models from service manager - - var seedCard = vmFactory.Get(); + + var seedCard = vmFactory.Get(); seedCard.GenerateNewSeed(); ImageGalleryCardViewModel = vmFactory.Get(); PromptCardViewModel = vmFactory.Get(); StackCardViewModel = vmFactory.Get(); - - StackCardViewModel.AddCards(new LoadableViewModelBase[] - { - // Model Card - vmFactory.Get(), - // Sampler - vmFactory.Get(), - // Hires Fix - vmFactory.Get(stackExpander => + + StackCardViewModel.AddCards( + new LoadableViewModelBase[] { - stackExpander.Title = "Hires Fix"; - stackExpander.AddCards(new LoadableViewModelBase[] + // Model Card + vmFactory.Get(), + // Sampler + vmFactory.Get(), + // Hires Fix + vmFactory.Get(stackExpander => + { + stackExpander.Title = "Hires Fix"; + stackExpander.AddCards( + new LoadableViewModelBase[] + { + // Hires Fix Upscaler + vmFactory.Get(), + // Hires Fix Sampler + vmFactory.Get(samplerCard => + { + samplerCard.IsDimensionsEnabled = false; + samplerCard.IsCfgScaleEnabled = false; + samplerCard.IsSamplerSelectionEnabled = false; + samplerCard.IsDenoiseStrengthEnabled = true; + }) + } + ); + }), + vmFactory.Get(stackExpander => { - // Hires Fix Upscaler - vmFactory.Get(), - // Hires Fix Sampler - vmFactory.Get(samplerCard => - { - samplerCard.IsDimensionsEnabled = false; - samplerCard.IsCfgScaleEnabled = false; - samplerCard.IsSamplerSelectionEnabled = false; - samplerCard.IsDenoiseStrengthEnabled = true; - }) - }); - }), - // Seed - seedCard, - // Batch Size - vmFactory.Get(), - }); + stackExpander.Title = "Upscale"; + stackExpander.AddCards( + new LoadableViewModelBase[] + { + // Post processing upscaler + vmFactory.Get(), + }); + }), + // Seed + seedCard, + // Batch Size + vmFactory.Get(), + } + ); GenerateImageCommand.WithNotificationErrorHandler(notificationService); } @@ -123,7 +135,7 @@ public partial class InferenceTextToImageViewModel : InferenceTabViewModelBase private (NodeDictionary prompt, string[] outputs) BuildPrompt() { using var _ = new CodeTimer(); - + var samplerCard = StackCardViewModel.GetCard(); var batchCard = StackCardViewModel.GetCard(); var modelCard = StackCardViewModel.GetCard(); @@ -131,144 +143,179 @@ public partial class InferenceTextToImageViewModel : InferenceTabViewModelBase var prompt = new NodeDictionary(); var builder = new ComfyNodeBuilder(prompt); - - var checkpointLoader = prompt.AddNamedNode(new NamedComfyNode("CheckpointLoader") - { - ClassType = "CheckpointLoaderSimple", - Inputs = new Dictionary + + var checkpointLoader = prompt.AddNamedNode( + new NamedComfyNode("CheckpointLoader") { - ["ckpt_name"] = modelCard.SelectedModelName + ClassType = "CheckpointLoaderSimple", + Inputs = new Dictionary + { + ["ckpt_name"] = modelCard.SelectedModelName + } } - }); + ); var checkpointVae = checkpointLoader.GetOutput(2); - - var emptyLatentImage = prompt.AddNamedNode(new NamedComfyNode("EmptyLatentImage") - { - ClassType = "EmptyLatentImage", - Inputs = new Dictionary + + var emptyLatentImage = prompt.AddNamedNode( + new NamedComfyNode("EmptyLatentImage") { - ["batch_size"] = batchCard.BatchSize, - ["height"] = samplerCard.Height, - ["width"] = samplerCard.Width, + ClassType = "EmptyLatentImage", + Inputs = new Dictionary + { + ["batch_size"] = batchCard.BatchSize, + ["height"] = samplerCard.Height, + ["width"] = samplerCard.Width, + } } - }); - - var positiveClip = prompt.AddNamedNode(new NamedComfyNode("PositiveCLIP") - { - ClassType = "CLIPTextEncode", - Inputs = new Dictionary + ); + + var positiveClip = prompt.AddNamedNode( + new NamedComfyNode("PositiveCLIP") { - ["clip"] = checkpointLoader.GetOutput(1), - ["text"] = PromptCardViewModel.PromptDocument.Text, + ClassType = "CLIPTextEncode", + Inputs = new Dictionary + { + ["clip"] = checkpointLoader.GetOutput(1), + ["text"] = PromptCardViewModel.PromptDocument.Text, + } } - }); - - var negativeClip = prompt.AddNamedNode(new NamedComfyNode("NegativeCLIP") - { - ClassType = "CLIPTextEncode", - Inputs = new Dictionary + ); + + var negativeClip = prompt.AddNamedNode( + new NamedComfyNode("NegativeCLIP") { - ["clip"] = checkpointLoader.GetOutput(1), - ["text"] = PromptCardViewModel.NegativePromptDocument.Text, + ClassType = "CLIPTextEncode", + Inputs = new Dictionary + { + ["clip"] = checkpointLoader.GetOutput(1), + ["text"] = PromptCardViewModel.NegativePromptDocument.Text, + } } - }); - - var sampler = prompt.AddNamedNode(ComfyNodeBuilder.KSampler( - "Sampler", - checkpointLoader.GetOutput(0), - Convert.ToUInt64(seedCard.Seed), - samplerCard.Steps, - samplerCard.CfgScale, - samplerCard.SelectedSampler?.Name ?? throw new InvalidOperationException("Sampler not selected"), - "normal", - positiveClip.GetOutput(0), - negativeClip.GetOutput(0), - emptyLatentImage.GetOutput(0), - samplerCard.DenoiseStrength)); + ); + + var sampler = prompt.AddNamedNode( + ComfyNodeBuilder.KSampler( + "Sampler", + checkpointLoader.GetOutput(0), + Convert.ToUInt64(seedCard.Seed), + samplerCard.Steps, + samplerCard.CfgScale, + samplerCard.SelectedSampler?.Name + ?? throw new InvalidOperationException("Sampler not selected"), + "normal", + positiveClip.GetOutput(0), + negativeClip.GetOutput(0), + emptyLatentImage.GetOutput(0), + samplerCard.DenoiseStrength + ) + ); + + var lastLatent = sampler.Output; + var lastLatentWidth = samplerCard.Width; + var lastLatentHeight = samplerCard.Height; - var vaeDecoder = prompt.AddNamedNode(new NamedComfyNode("VAEDecoder") - { - ClassType = "VAEDecode", - Inputs = new Dictionary + var vaeDecoder = prompt.AddNamedNode( + new NamedComfyNode("VAEDecoder") { - ["samples"] = sampler.GetOutput(0), - ["vae"] = checkpointLoader.GetOutput(2) + ClassType = "VAEDecode", + Inputs = new Dictionary + { + ["samples"] = lastLatent, + ["vae"] = checkpointLoader.GetOutput(2) + } } - }); - - var saveImage = prompt.AddNamedNode(new NamedComfyNode("SaveImage") - { - ClassType = "SaveImage", - Inputs = new Dictionary + ); + + var saveImage = prompt.AddNamedNode( + new NamedComfyNode("SaveImage") { - ["filename_prefix"] = "SM-Inference", - ["images"] = vaeDecoder.GetOutput(0) + ClassType = "SaveImage", + Inputs = new Dictionary + { + ["filename_prefix"] = "SM-Inference", + ["images"] = vaeDecoder.GetOutput(0) + } } - }); + ); // If hi-res fix is enabled, add the LatentUpscale node and another KSampler node if (IsHiresFixEnabled) { var hiresUpscalerCard = UpscalerCardViewModel; var hiresSamplerCard = HiresSamplerCardViewModel; + + // Requested upscale to this size + var hiresWidth = (int)Math.Floor(lastLatentWidth * hiresUpscalerCard.Scale); + var hiresHeight = (int)Math.Floor(lastLatentHeight * hiresUpscalerCard.Scale); + + LatentNodeConnection hiresLatent; // Select between latent upscale and normal upscale based on the upscale method - var selectedUpscaler = hiresUpscalerCard.SelectedUpscaler; - - LatentNodeConnection hiresOutput; + var selectedUpscaler = hiresUpscalerCard.SelectedUpscaler!.Value; - if (selectedUpscaler?.Type == ComfyUpscalerType.Latent) - { - hiresOutput = prompt.AddNamedNode(new NamedComfyNode("LatentUpscale") - { - ClassType = "LatentUpscale", - Inputs = new Dictionary - { - ["upscale_method"] = hiresUpscalerCard.SelectedUpscaler?.Name, - ["width"] = samplerCard.Width * hiresUpscalerCard.Scale, - ["height"] = samplerCard.Height * hiresUpscalerCard.Scale, - ["crop"] = "disabled", - ["samples"] = sampler.Output - } - }).GetOutput(0); - } - else if (selectedUpscaler?.Type == ComfyUpscalerType.ESRGAN) + if (selectedUpscaler.Type == ComfyUpscalerType.None) { - // Convert to image space - var samplerImage = builder.Lambda_LatentToImage(sampler.Output, checkpointVae); - // Do group upscale - var modelUpscaler = builder.Group_UpscaleWithModel("Upscaler", - selectedUpscaler.Value.Name, samplerImage); - // Convert back to latent space - hiresOutput = builder.Lambda_ImageToLatent(modelUpscaler.Output, checkpointVae); + // If no upscaler selected or none, just reroute the latent image + hiresLatent = sampler.Output; } else { - // If no upscaler selected or none, just reroute the latent image - hiresOutput = sampler.Output; + // Otherwise upscale the latent image + hiresLatent = builder.Group_UpscaleToLatent("HiresFix", + lastLatent, checkpointVae, selectedUpscaler, hiresWidth, hiresHeight).Output; } - var hiresSampler = prompt.AddNamedNode(ComfyNodeBuilder.KSampler( - "HiresSampler", - checkpointLoader.GetOutput(0), - Convert.ToUInt64(seedCard.Seed), - hiresSamplerCard.Steps, - hiresSamplerCard.CfgScale, - // Use hires sampler name if not null, otherwise use the normal sampler name - hiresSamplerCard.SelectedSampler?.Name ?? samplerCard.SelectedSampler?.Name ?? throw new InvalidOperationException("Sampler not selected"), - "normal", - positiveClip.GetOutput(0), - negativeClip.GetOutput(0), - hiresOutput, - hiresSamplerCard.DenoiseStrength)); - + var hiresSampler = prompt.AddNamedNode( + ComfyNodeBuilder.KSampler( + "HiresSampler", + checkpointLoader.GetOutput(0), + Convert.ToUInt64(seedCard.Seed), + hiresSamplerCard.Steps, + hiresSamplerCard.CfgScale, + // Use hires sampler name if not null, otherwise use the normal sampler name + hiresSamplerCard.SelectedSampler?.Name + ?? samplerCard.SelectedSampler?.Name + ?? throw new InvalidOperationException("Sampler not selected"), + "normal", + positiveClip.GetOutput(0), + negativeClip.GetOutput(0), + hiresLatent, + hiresSamplerCard.DenoiseStrength + ) + ); + + // Set as last latent + lastLatent = hiresSampler.Output; + lastLatentWidth = hiresWidth; + lastLatentHeight = hiresHeight; // Reroute the VAEDecoder's input to be from the hires sampler - vaeDecoder.Inputs["samples"] = hiresSampler.Output; + vaeDecoder.Inputs["samples"] = lastLatent; + } + + // If upscale is enabled, add another upscale group + if (IsUpscaleEnabled) + { + var postUpscalerCard = StackCardViewModel.GetCard(1) + .GetCard(); + + var upscaleWidth = (int)Math.Floor(lastLatentWidth * postUpscalerCard.Scale); + var upscaleHeight = (int)Math.Floor(lastLatentHeight * postUpscalerCard.Scale); + + // Build group + var postUpscaleGroup = builder.Group_UpscaleToImage("PostUpscale", + lastLatent, checkpointVae, postUpscalerCard.SelectedUpscaler!.Value, + upscaleWidth, upscaleHeight); + + // Remove the original vae decoder + prompt.Remove(vaeDecoder.Name); + + // Set as the input for save image + saveImage.Inputs["images"] = postUpscaleGroup.Output; } prompt.NormalizeConnectionTypes(); - + return (prompt, new[] { saveImage.Name }); } @@ -278,8 +325,9 @@ public partial class InferenceTextToImageViewModel : InferenceTabViewModelBase OutputProgress.Maximum = args.Maximum; OutputProgress.IsIndeterminate = false; - OutputProgress.Text = $"({args.Value} / {args.Maximum})" - + (args.RunningNode != null ? $" {args.RunningNode}" : ""); + OutputProgress.Text = + $"({args.Value} / {args.Maximum})" + + (args.RunningNode != null ? $" {args.RunningNode}" : ""); } private void OnPreviewImageReceived(object? sender, ComfyWebSocketImageData args) @@ -315,7 +363,7 @@ public partial class InferenceTextToImageViewModel : InferenceTabViewModelBase // Connect progress handler // client.ProgressUpdateReceived += OnProgressUpdateReceived; client.PreviewImageReceived += OnPreviewImageReceived; - + ComfyTask? promptTask = null; try { @@ -323,9 +371,11 @@ public partial class InferenceTextToImageViewModel : InferenceTabViewModelBase cancellationToken.Register(() => { Logger.Info("Cancelling prompt"); - client.InterruptPromptAsync(new CancellationTokenSource(5000).Token).SafeFireAndForget(); + client + .InterruptPromptAsync(new CancellationTokenSource(5000).Token) + .SafeFireAndForget(); }); - + try { promptTask = await client.QueuePromptAsync(nodes, cancellationToken); @@ -336,7 +386,7 @@ public partial class InferenceTextToImageViewModel : InferenceTabViewModelBase await DialogHelper.CreateApiExceptionDialog(e, "Api Error").ShowAsync(); return; } - + // Register progress handler promptTask.ProgressUpdate += OnProgressUpdateReceived; @@ -351,9 +401,10 @@ public partial class InferenceTextToImageViewModel : InferenceTabViewModelBase ); ImageGalleryCardViewModel.ImageSources.Clear(); - + var images = imageOutputs[outputNodeNames[0]]; - if (images is null) return; + if (images is null) + return; List outputImages; // Use local file path if available, otherwise use remote URL @@ -369,26 +420,27 @@ public partial class InferenceTextToImageViewModel : InferenceTabViewModelBase .Select(i => new ImageSource(i.ToUri(client.BaseAddress))) .ToList(); } - + // Download all images to make grid, if multiple if (outputImages.Count > 1) { - var loadedImages = outputImages.Select(i => - SKImage.FromEncodedData(i.LocalFile?.Info.OpenRead())).ToImmutableArray(); + var loadedImages = outputImages + .Select(i => SKImage.FromEncodedData(i.LocalFile?.Info.OpenRead())) + .ToImmutableArray(); var grid = ImageProcessor.CreateImageGrid(loadedImages); - + // Save to disk var lastName = outputImages.Last().LocalFile?.Info.Name; var gridPath = client.OutputImagesDir!.JoinFile($"grid-{lastName}"); await using var fileStream = gridPath.Info.OpenWrite(); await fileStream.WriteAsync(grid.Encode().ToArray(), cancellationToken); - + // Insert to start of images ImageGalleryCardViewModel.ImageSources.Add(new ImageSource(gridPath)); } - + // Add rest of images ImageGalleryCardViewModel.ImageSources.AddRange(outputImages); } @@ -400,7 +452,7 @@ public partial class InferenceTextToImageViewModel : InferenceTabViewModelBase ImageGalleryCardViewModel.PreviewImage?.Dispose(); ImageGalleryCardViewModel.PreviewImage = null; ImageGalleryCardViewModel.IsPreviewOverlayEnabled = false; - + // client.ProgressUpdateReceived -= OnProgressUpdateReceived; promptTask?.Dispose(); client.PreviewImageReceived -= OnPreviewImageReceived; diff --git a/StabilityMatrix.Avalonia/ViewModels/Inference/StackExpanderViewModel.cs b/StabilityMatrix.Avalonia/ViewModels/Inference/StackExpanderViewModel.cs index f6366ece..2b4e3c2e 100644 --- a/StabilityMatrix.Avalonia/ViewModels/Inference/StackExpanderViewModel.cs +++ b/StabilityMatrix.Avalonia/ViewModels/Inference/StackExpanderViewModel.cs @@ -1,24 +1,29 @@ using System.Linq; using System.Text.Json.Nodes; using CommunityToolkit.Mvvm.ComponentModel; +using Newtonsoft.Json; using StabilityMatrix.Avalonia.Controls; using StabilityMatrix.Avalonia.Models.Inference; using StabilityMatrix.Core.Attributes; using StabilityMatrix.Core.Extensions; +#pragma warning disable CS0657 // Not a valid attribute location for this declaration namespace StabilityMatrix.Avalonia.ViewModels.Inference; [View(typeof(StackExpander))] public partial class StackExpanderViewModel : StackViewModelBase { - [ObservableProperty] private string? title; - [ObservableProperty] private bool isEnabled; + [ObservableProperty] + [property: JsonIgnore] + private string? title; + + [ObservableProperty] + private bool isEnabled; /// public override void LoadStateFromJsonObject(JsonObject state) { var model = DeserializeModel(state); - Title = model.Title; IsEnabled = model.IsEnabled; if (model.Cards is null) return; @@ -37,7 +42,6 @@ public partial class StackExpanderViewModel : StackViewModelBase { return SerializeModel(new StackExpanderModel { - Title = Title, IsEnabled = IsEnabled, Cards = Cards.Select(x => x.SaveStateToJsonObject()).ToList() }); diff --git a/StabilityMatrix.Avalonia/ViewModels/SettingsViewModel.cs b/StabilityMatrix.Avalonia/ViewModels/SettingsViewModel.cs index 405e97cd..bb181c8f 100644 --- a/StabilityMatrix.Avalonia/ViewModels/SettingsViewModel.cs +++ b/StabilityMatrix.Avalonia/ViewModels/SettingsViewModel.cs @@ -650,8 +650,8 @@ public partial class SettingsViewModel : PageViewModelBase var imageBox = new ImageViewerDialog() { - MinWidth = 1500, - MinHeight = 900, + Width = 1000, + Height = 1000, DataContext = new ImageViewerViewModel() { Image = bitmap @@ -661,9 +661,10 @@ public partial class SettingsViewModel : PageViewModelBase var dialog = new BetterContentDialog { MaxDialogWidth = 1000, + MaxDialogHeight = 1000, FullSizeDesired = true, Content = imageBox, - CloseButtonText = "Close", + IsFooterVisible = false, ContentVerticalScrollBarVisibility = ScrollBarVisibility.Disabled, }; diff --git a/StabilityMatrix.Avalonia/Views/Dialogs/ImageViewerDialog.axaml b/StabilityMatrix.Avalonia/Views/Dialogs/ImageViewerDialog.axaml index dc05faf0..c1956262 100644 --- a/StabilityMatrix.Avalonia/Views/Dialogs/ImageViewerDialog.axaml +++ b/StabilityMatrix.Avalonia/Views/Dialogs/ImageViewerDialog.axaml @@ -8,23 +8,38 @@ xmlns:controls="clr-namespace:StabilityMatrix.Avalonia.Controls" xmlns:system="clr-namespace:System;assembly=System.Runtime" xmlns:vmDialogs="clr-namespace:StabilityMatrix.Avalonia.ViewModels.Dialogs" + xmlns:icons="clr-namespace:Projektanker.Icons.Avalonia;assembly=Projektanker.Icons.Avalonia" + VerticalContentAlignment="Stretch" + HorizontalContentAlignment="Stretch" d:DataContext="{x:Static mocks:DesignData.ImageViewerViewModel}" x:DataType="vmDialogs:ImageViewerViewModel" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" x:Class="StabilityMatrix.Avalonia.Views.Dialogs.ImageViewerDialog"> - + + Image="{Binding Image}" + Source="{Binding Source}"/> - + VerticalAlignment="Bottom"/> --> + + + +