我想在传入的绑定整数上添加一个常量值。事实上,我有几个地方,我想绑定到相同的源值,但添加不同的常量。所以理想的解决方案就是这样......
<TextBox Canvas.Top="{Binding ElementName=mySource, Path=myInt, Constant=5}"/>
<TextBox Canvas.Top="{Binding ElementName=mySource, Path=myInt, Constant=8}"/>
<TextBox Canvas.Top="{Binding ElementName=mySource, Path=myInt, Constant=24}"/>
(注意:这是一个展示这个想法的例子,我的实际绑定方案不是TextBox的canvas属性。但这更清楚地表明了这个想法)
目前我能想到的唯一解决方案是暴露许多不同的源属性,每个源属性都将不同的常量添加到相同的内部值。所以我可以做这样的事......
<TextBox Canvas.Top="{Binding ElementName=mySource, Path=myIntPlus5}"/>
<TextBox Canvas.Top="{Binding ElementName=mySource, Path=myIntPlus8}"/>
<TextBox Canvas.Top="{Binding ElementName=mySource, Path=myIntPlus24}"/>
但这非常严峻,因为将来我可能需要不断为新常量添加新属性。此外,如果我需要更改添加的值,我需要更改源对象,这是非常naff。
必须有比这更通用的方法吗?任何WPF专家都有任何想法吗?
答案 0 :(得分:19)
我使用我创建的MathConverter
来执行所有简单的算术运算。转换器的代码是here,它可以像这样使用:
<TextBox Canvas.Top="{Binding SomeValue,
Converter={StaticResource MathConverter},
ConverterParameter=@VALUE+5}" />
您甚至可以将其用于更高级的算术运算,例如
Width="{Binding ElementName=RootWindow, Path=ActualWidth,
Converter={StaticResource MathConverter},
ConverterParameter=((@VALUE-200)*.3)}"
答案 1 :(得分:7)
我相信你可以用价值转换器来做到这一点。这是一个blog entry,用于将参数传递给xaml中的值转换器。 this blog提供了实现值转换器的一些细节。
答案 2 :(得分:5)
使用值转换器是解决问题的好方法,因为它允许您在绑定到UI时修改源值。
我在几个地方使用了以下内容。
public class AddValueConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
object result = value;
int parameterValue;
if (value != null && targetType == typeof(Int32) &&
int.TryParse((string)parameter,
NumberStyles.Integer, culture, out parameterValue))
{
result = (int)value + (int)parameterValue;
}
return result;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
实施例
<Setter Property="Grid.ColumnSpan"
Value="{Binding
Path=ColumnDefinitions.Count,
RelativeSource={RelativeSource AncestorType=Grid},
Converter={StaticResource addValueConverter},
ConverterParameter=1}"
/>
答案 3 :(得分:0)
我从未使用过WPF,但我有一个可能的解决方案。
您的绑定路径可以映射到地图吗?如果是这样,它应该能够采取一个参数(密钥)。您需要创建一个实现Map接口的类,但实际上只返回初始化“Map”并添加到键中的基值。
public Integer get( Integer key ) { return baseInt + key; } // or some such
如果没有能力从标签中传递数字,我不会看到你如何让它从原始值返回不同的增量。
答案 4 :(得分:0)
我将使用多绑定转换器,例如以下示例:
C#代码:
namespace Example.Converters
{
public class ArithmeticConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
double result = 0;
for (int i = 0; i < values.Length; i++)
{
if (!double.TryParse(values[i]?.ToString(), out var parsedNumber)) continue;
if (TryGetOperations(parameter, i, out var operation))
{
result = operation(result, parsedNumber);
}
}
return result;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
return new[] { Binding.DoNothing, false };
}
private static bool TryGetOperations(object parameter, int operationIndex, out Func<double, double, double> operation)
{
operation = null;
var operations = parameter?.ToString().Split(',');
if (operations == null || operations.Length == 0) return false;
if (operations.Length <= operationIndex)
{
operationIndex = operations.Length - 1;
}
return Operations.TryGetValue(operations[operationIndex]?.ToString(), out operation);
}
public const string Add = "+";
public const string Subtract = "-";
public const string Multiply = "*";
public const string Divide = "/";
private static IDictionary<string, Func<double, double, double>> Operations = new Dictionary<string, Func<double, double, double>>
{
{ Add, (x, y) => x + y },
{ Subtract, (x, y) => x - y },
{ Multiply, (x, y) => x * y },
{ Divide, (x, y) => x / y }
};
}
}
XAML代码:
<UserControl
xmlns:converters="clr-namespace:Example.Converters">
<UserControl.Resources>
<converters:ArithmeticConverter x:Key="ArithmeticConverter" />
</UserControl.Resources>
...
<MultiBinding Converter="{StaticResource ArithmeticConverter}" ConverterParameter="+,-">
<Binding Path="NumberToAdd" />
<Binding Path="NumberToSubtract" />
</MultiBinding>