2009-11-25 93 views

回答

1

,能夠使用自定義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); 
     } 
    } 
} 

有了這個,你可以建立任意表達式樹(這是很多比數學解析字符串,如果你不介意的麻煩,你可以做,當然也更容易)。