¿Cómo definir el valor del recurso dinámico basado en un recurso más dinámico?

StackOverflow https://stackoverflow.com/questions/1796400

  •  22-09-2019
  •  | 
  •  

Pregunta

¿Es posible asignar valor a un recurso dinámico de otro recurso dinámico?
Por ejemplo

<sys:Double x:Key="ButtonWidth">48</sys:Double>
<sys:Double x:Key="SmallButtonWidth"> ButtonWidth / 2 </sys:Double>
¿Fue útil?

Solución

Es posible transformar un valor utilizando una costumbre MarkupExtension .

por ejemplo.

<Window.Resources xmlns:ms="clr-namespace:WpfApplication1.MathShit">
    <sys:Double x:Key="ButtonWidth">48</sys:Double>
    <ms:Calculation x:Key="SmallButtonWidth">
        <ms:Product Operand1="{ms:Value {StaticResource ButtonWidth}}"
                    Operand2="0.5" />
    </ms:Calculation>
</Window.Resources>
namespace WpfApplication1.MathShit
{
    [ContentProperty("Expression")]
    public class Calculation : MarkupExtension
    {
        public IExpression Expression { get; set; }

        public override object ProvideValue(IServiceProvider serviceProvider)
        {
            if (Expression == null) throw new Exception("Expression cannot be null.");

            return Expression.CalculateValue();
        }
    }

    [TypeConverter(typeof(ExpressionConverter))]
    public interface IExpression
    {
        double CalculateValue();
    }

    public abstract class BinaryOperation : IExpression
    {
        public IExpression Operand1 { get; set; }
        public IExpression Operand2 { get; set; }

        public double CalculateValue()
        {
            if (Operand1 == null) throw new Exception("Operand1 cannot be null.");
            if (Operand2 == null) throw new Exception("Operand2 cannot be null.");

            return CalculateBinaryOperation();
        }

        protected abstract double CalculateBinaryOperation();
    }
    public class Sum : BinaryOperation
    {
        protected override double CalculateBinaryOperation()
        {
            return Operand1.CalculateValue() + Operand2.CalculateValue();
        }
    }
    public class Product : BinaryOperation
    {
        protected override double CalculateBinaryOperation()
        {
            return Operand1.CalculateValue() * Operand2.CalculateValue();
        }
    }
    public class Value : MarkupExtension, IExpression
    {
        public double? Double { get; set; }

        public Value() { }
        public Value(double @double)
            : this()
        {
            this.Double = @double;
        }

        public double CalculateValue()
        {
            if (Double == null) throw new Exception("Double");

            return Double.Value;
        }

        // Allows easy object instantiation in XAML attributes. (Result of StaticResource is not piped through ExpressionConverter.)
        public override object ProvideValue(IServiceProvider serviceProvider)
        {
            return this;
        }
    }

    public class ExpressionConverter : DoubleConverter
    {
        public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
        {
            var doubleValue = (double)base.ConvertFrom(context, culture, value);
            return (IExpression)new Value(doubleValue);
        }

        public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
        {
            var val = (Value)value;
            return base.ConvertTo(context, culture, val.CalculateValue(), destinationType);
        }
    }
}

Con esto se puede construir árboles de expresión arbitrarias (que es mucho más fácil de analizar cadenas de matemáticas que se puede hacer también, por supuesto, si no te importa la molestia).

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top