Se añadió un estilo global para TreeViewItem en App.xaml para evitar errores de binding. Se actualizaron las referencias de paquetes en CtrEditor.csproj, cambiando la versión de LiveChartsCore.SkiaSharpView.WPF y añadiendo SkiaSharp.Views.WPF. Se mejoró la gestión de carga de imágenes en osBase.cs y ucCustomImage.xaml.cs, implementando un manejo de errores más robusto y estableciendo imágenes por defecto en caso de fallos. Se ajustó el XAML de ucBoolTag para mejorar la conversión de color. Se implementó un convertidor seguro para ImageSource en StateSerializer.cs, mejorando la deserialización de imágenes.
This commit is contained in:
parent
3af9ad99d8
commit
5c2daaeb98
6
App.xaml
6
App.xaml
|
@ -22,6 +22,12 @@
|
|||
<local:SubclassFilterConverter x:Key="SubclassFilterConverterosVMMotor" TargetType="{x:Type os:osVMmotorSim}" />
|
||||
<local:UnsavedChangesConverter x:Key="UnsavedChangesConverter"/>
|
||||
<local:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
|
||||
|
||||
<!-- Estilo global para TreeViewItem para evitar errores de binding -->
|
||||
<Style TargetType="TreeViewItem">
|
||||
<Setter Property="HorizontalContentAlignment" Value="Left"/>
|
||||
<Setter Property="VerticalContentAlignment" Value="Center"/>
|
||||
</Style>
|
||||
</Application.Resources>
|
||||
</Application>
|
||||
|
||||
|
|
|
@ -85,8 +85,9 @@
|
|||
<PackageReference Include="Emgu.CV.UI" Version="4.9.0.5494" />
|
||||
<PackageReference Include="Extended.Wpf.Toolkit" Version="4.7.25104.5739" />
|
||||
<PackageReference Include="LanguageDetection" Version="1.2.0" />
|
||||
<PackageReference Include="LiveChartsCore.SkiaSharpView.WPF" Version="2.0.0-rc4.5" />
|
||||
<PackageReference Include="LiveChartsCore.SkiaSharpView.WPF" Version="2.0.0-rc3.3" />
|
||||
<PackageReference Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.135" />
|
||||
<PackageReference Include="SkiaSharp.Views.WPF" Version="2.88.8" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="Ookii.Dialogs.Wpf" Version="5.0.1" />
|
||||
<PackageReference Include="PaddleOCRSharp" Version="4.5.0.1" />
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using LibS7Adv;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
using CtrEditor.FuncionesBase;
|
||||
using System.ComponentModel;
|
||||
|
@ -27,11 +27,42 @@ namespace CtrEditor.ObjetosSim
|
|||
}
|
||||
|
||||
|
||||
[ObservableProperty]
|
||||
[NotifyPropertyChangedFor(nameof(ImageSource_oculta))]
|
||||
[property: Description("Path to the image file")]
|
||||
[property: Category("Image:")]
|
||||
private string imagePath;
|
||||
private string _imagePath;
|
||||
|
||||
[Description("Path to the image file")]
|
||||
[Category("Image:")]
|
||||
public string ImagePath
|
||||
{
|
||||
get => _imagePath;
|
||||
set
|
||||
{
|
||||
try
|
||||
{
|
||||
if (SetProperty(ref _imagePath, value))
|
||||
{
|
||||
OnImagePathChanged(value);
|
||||
OnPropertyChanged(nameof(ImageSource_oculta));
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Si hay error al establecer la propiedad, simplemente ignorarlo
|
||||
// y establecer la imagen por defecto
|
||||
try
|
||||
{
|
||||
SetProperty(ref _imagePath, value);
|
||||
ImageSource_oculta = ImageFromPath("/Icons/unselect.png");
|
||||
OnPropertyChanged(nameof(ImageSource_oculta));
|
||||
}
|
||||
catch
|
||||
{
|
||||
// En caso de error total, establecer valores seguros
|
||||
_imagePath = value;
|
||||
ImageSource_oculta = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[ObservableProperty]
|
||||
[property: Description("Flip the image horizontally")]
|
||||
|
@ -48,16 +79,32 @@ namespace CtrEditor.ObjetosSim
|
|||
[ObservableProperty]
|
||||
public ImageSource imageSource_oculta;
|
||||
|
||||
partial void OnImagePathChanged(string value)
|
||||
private void OnImagePathChanged(string value)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(value))
|
||||
try
|
||||
{
|
||||
ImageSource_oculta = ImageFromPath(value);
|
||||
if (!string.IsNullOrEmpty(value))
|
||||
{
|
||||
ImageSource_oculta = ImageFromPath(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Si no hay path, usar la imagen por defecto
|
||||
ImageSource_oculta = ImageFromPath("/Icons/unselect.png");
|
||||
}
|
||||
}
|
||||
else
|
||||
catch
|
||||
{
|
||||
// Si no hay path, usar la imagen por defecto
|
||||
ImageSource_oculta = ImageFromPath("/Icons/unselect.png");
|
||||
// Si hay cualquier error, usar la imagen por defecto
|
||||
try
|
||||
{
|
||||
ImageSource_oculta = ImageFromPath("/Icons/unselect.png");
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Si incluso la imagen por defecto falla, establecer como null
|
||||
ImageSource_oculta = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -82,14 +129,30 @@ namespace CtrEditor.ObjetosSim
|
|||
public override void ucLoaded()
|
||||
{
|
||||
base.ucLoaded();
|
||||
if (!string.IsNullOrEmpty(ImagePath))
|
||||
try
|
||||
{
|
||||
ImageSource_oculta = ImageFromPath(ImagePath);
|
||||
if (!string.IsNullOrEmpty(ImagePath))
|
||||
{
|
||||
ImageSource_oculta = ImageFromPath(ImagePath);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Si no hay path al cargar, usar la imagen por defecto
|
||||
ImageSource_oculta = ImageFromPath("/Icons/unselect.png");
|
||||
}
|
||||
}
|
||||
else
|
||||
catch
|
||||
{
|
||||
// Si no hay path al cargar, usar la imagen por defecto
|
||||
ImageSource_oculta = ImageFromPath("/Icons/unselect.png");
|
||||
// Si hay cualquier error, usar la imagen por defecto
|
||||
try
|
||||
{
|
||||
ImageSource_oculta = ImageFromPath("/Icons/unselect.png");
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Si incluso la imagen por defecto falla, establecer como null
|
||||
ImageSource_oculta = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
Width="16" Height="25" VerticalAlignment="Center" HorizontalAlignment="Center"
|
||||
Background="{Binding Color, Converter={StaticResource ColorToBrushConverter}}" />
|
||||
<Label Content="{Binding Descripcion}" Grid.Column="1" VerticalAlignment="Center"
|
||||
Background="{Binding Color}"
|
||||
Background="{Binding Color, Converter={StaticResource ColorToBrushConverter}}"
|
||||
Visibility="{Binding Show_Description, Converter={StaticResource BooleanToVisibilityConverter}}" />
|
||||
<CheckBox Grid.Column="2" VerticalAlignment="Center" IsChecked="{Binding Estado}"
|
||||
Background="{Binding Color_oculto}" />
|
||||
|
|
|
@ -1642,7 +1642,31 @@ namespace CtrEditor.ObjetosSim
|
|||
{
|
||||
if (value is string stringValue)
|
||||
{
|
||||
return new BitmapImage(new Uri(stringValue, UriKind.RelativeOrAbsolute));
|
||||
try
|
||||
{
|
||||
var bitmapImage = new BitmapImage();
|
||||
bitmapImage.BeginInit();
|
||||
bitmapImage.UriSource = new Uri(stringValue, UriKind.RelativeOrAbsolute);
|
||||
bitmapImage.EndInit();
|
||||
return bitmapImage;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Si falla la carga de la imagen, usar imagen por defecto como fallback
|
||||
try
|
||||
{
|
||||
var defaultImage = new BitmapImage();
|
||||
defaultImage.BeginInit();
|
||||
defaultImage.UriSource = new Uri("/Icons/unselect.png", UriKind.RelativeOrAbsolute);
|
||||
defaultImage.EndInit();
|
||||
return defaultImage;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Si incluso la imagen por defecto falla, devolver null
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ using System.Windows;
|
|||
using CtrEditor.Simulacion;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace CtrEditor.Serialization
|
||||
{
|
||||
|
@ -254,8 +255,89 @@ namespace CtrEditor.Serialization
|
|||
NullValueHandling = NullValueHandling.Ignore,
|
||||
TypeNameHandling = TypeNameHandling.Auto,
|
||||
ObjectCreationHandling = ObjectCreationHandling.Replace,
|
||||
ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor
|
||||
ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor,
|
||||
Error = HandleDeserializationError,
|
||||
Converters = { new SafeImageSourceConverter() }
|
||||
};
|
||||
}
|
||||
|
||||
private void HandleDeserializationError(object sender, Newtonsoft.Json.Serialization.ErrorEventArgs e)
|
||||
{
|
||||
// Si es un error relacionado con ImagePath, ImageSource o osCustomImage, simplemente ignorarlo y continuar
|
||||
if (e.ErrorContext.Error.Message.Contains("ImagePath") ||
|
||||
e.ErrorContext.Error.Message.Contains("osCustomImage") ||
|
||||
e.ErrorContext.Error.Message.Contains("ImageSource") ||
|
||||
e.ErrorContext.Error.Message.Contains("lmageSource") || // posible typo en el mensaje de error
|
||||
(e.ErrorContext.Path != null && e.ErrorContext.Path.Contains("ImageSource")) ||
|
||||
(e.ErrorContext.Path != null && e.ErrorContext.Path.Contains("imagePath")) ||
|
||||
(e.ErrorContext.Member != null && e.ErrorContext.Member.ToString().Contains("Image")))
|
||||
{
|
||||
e.ErrorContext.Handled = true;
|
||||
|
||||
// Si el contexto actual es un objeto osCustomImage y hay un error,
|
||||
// intentar establecer valores por defecto
|
||||
if (e.ErrorContext.OriginalObject is osCustomImage customImage)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Establecer valores seguros por defecto
|
||||
if (e.ErrorContext.Member?.ToString() == "ImagePath" ||
|
||||
e.ErrorContext.Member?.ToString() == "imagePath")
|
||||
{
|
||||
customImage.ImagePath = ""; // Esto activará el fallback a imagen por defecto
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Si incluso esto falla, simplemente ignorar
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convertidor JSON seguro para ImageSource que nunca lanza excepciones
|
||||
/// </summary>
|
||||
public class SafeImageSourceConverter : JsonConverter<ImageSource>
|
||||
{
|
||||
public override ImageSource ReadJson(JsonReader reader, Type objectType, ImageSource existingValue, bool hasExistingValue, JsonSerializer serializer)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Si el valor es null o string vacío, devolver null
|
||||
if (reader.Value == null || reader.Value.ToString() == "")
|
||||
return null;
|
||||
|
||||
// Intentar crear ImageSource desde el valor
|
||||
string value = reader.Value.ToString();
|
||||
|
||||
// Limpiar caracteres problemáticos
|
||||
value = value.Trim();
|
||||
if (value.Contains("•"))
|
||||
value = value.Replace("•", "");
|
||||
if (value.StartsWith("filet///"))
|
||||
value = value.Replace("filet///", "file:///");
|
||||
|
||||
// Si el valor limpio está vacío, devolver null
|
||||
if (string.IsNullOrWhiteSpace(value))
|
||||
return null;
|
||||
|
||||
// No intentar crear ImageSource aquí, simplemente devolver null
|
||||
// La lógica de carga de imagen se manejará en el código de la aplicación
|
||||
return null;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// En caso de cualquier error, devolver null silenciosamente
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public override void WriteJson(JsonWriter writer, ImageSource value, JsonSerializer serializer)
|
||||
{
|
||||
// Nunca serializar ImageSource, siempre escribir null
|
||||
writer.WriteNull();
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue