Как определить значение динамического ресурса на основе другого динамического ресурса?

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

  •  22-09-2019
  •  | 
  •  

Вопрос

Можно ли присвоить значение динамическому ресурсу из другого динамического ресурса?
Например

<sys:Double x:Key="ButtonWidth">48</sys:Double>
<sys:Double x:Key="SmallButtonWidth"> ButtonWidth / 2 </sys:Double>
Это было полезно?

Решение

Можно преобразовать значение с помощью пользовательского MarkupExtension.

например

<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);
        }
    }
}

С его помощью вы можете строить произвольные деревья выражений (что намного проще, чем анализ математических строк, которые вы тоже можете делать, если вас это не беспокоит).

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top