값은 사용자가 구성 될 운명하는 경우
(값 만 MainWindow
사용하는 경우 또는 MainWindowSettings
)
나는 보통 ApplicationSettings
처럼 일반적인 뭔가라는 단일 정적 또는 싱글 톤 클래스의 모든 정적 내 응용 프로그램 설정을 넣어 그들은 app.config에 가서 정적 클래스의 생성자에로드됩니다. 그렇지 않다면 정적 클래스에서 코드를 하드 코딩하기 때문에 나중에 쉽게 찾을 수 있습니다. 당신의 XAML에서 계산 된 값에 대한
public static class ApplicationSettings
{
public static Double MarginInner { get; private set; }
public static Double MarginOuter { get; private set; }
public static Double StrokeThickness { get; private set; }
static ApplicationSettings()
{
MarginInner = 6D;
MarginOuter = 10D;
StrokeThickness = 3D;
}
}
, 나는 일반적으로 MathConverter 내가 그 날은 수학 식 바인딩 작성하고 사용하도록에게 값을 전달 할 수 있습니다 썼다 사용합니다.
내 블로그에 게시 한 버전은 IValueConverter
이지만 IMultiValueConverter
으로 확장하기가 쉽기 때문에 다중 바인딩 된 값을 허용 할 수 있습니다.
<Setter Property="Height">
<Setter.Value>
<MultiBinding Converter="{StaticResource MathMultiConverter}"
ConverterParameter="(@VALUE1 * 2D) + (@VALUE2 * 3D) + (@VALUE3 * 2.5D)">
<Binding RelativeSource="{x:Static ns:ApplicationSettings.StrokeThickness }" />
<Binding RelativeSource="{x:Static ns:ApplicationSettings.MarginInner}" />
<Binding ElementName="MyUc" Path="ActualHeight" />
</MultiBinding>
</Setter.Value>
</Setter>
는 일반적으로 나는 어딘가 스타일의이 모든 혼란 XAML을 숨길 것, 그래서 내 주요 XAML 코드를 복잡하게하지 않고, 단지 필요한 스타일을 적용합니다. 여기
내가 사용 컨버터 코드의 사본 년대
IMultiValueConvter
// Does a math equation on a series of bound values.
// Use @VALUEN in your mathEquation as a substitute for bound values, where N is the 0-based index of the bound value
// Operator order is parenthesis first, then Left-To-Right (no operator precedence)
public class MathMultiConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
// Remove spaces
var mathEquation = parameter as string;
mathEquation = mathEquation.Replace(" ", "");
// Loop through values to substitute placeholders for values
// Using a backwards loop to avoid replacing something like @VALUE10 with @VALUE1
for (var i = (values.Length - 1); i >= 0; i--)
mathEquation = mathEquation.Replace(string.Format("@VALUE{0}", i), values[i].ToString());
// Return result of equation
return MathConverterHelpers.RunEquation(ref mathEquation);
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
public static class MathConverterHelpers
{
private static readonly char[] _allOperators = new[] { '+', '-', '*', '/', '%', '(', ')' };
private static readonly List<string> _grouping = new List<string> { "(", ")" };
private static readonly List<string> _operators = new List<string> { "+", "-", "*", "/", "%" };
public static double RunEquation(ref string mathEquation)
{
// Validate values and get list of numbers in equation
var numbers = new List<double>();
double tmp;
foreach (string s in mathEquation.Split(_allOperators))
{
if (s != string.Empty)
{
if (double.TryParse(s, out tmp))
{
numbers.Add(tmp);
}
else
{
// Handle Error - Some non-numeric, operator, or grouping character found in string
throw new InvalidCastException();
}
}
}
// Begin parsing method
EvaluateMathString(ref mathEquation, ref numbers, 0);
// After parsing the numbers list should only have one value - the total
return numbers[0];
}
// Evaluates a mathematical string and keeps track of the results in a List<double> of numbers
private static void EvaluateMathString(ref string mathEquation, ref List<double> numbers, int index)
{
// Loop through each mathemtaical token in the equation
string token = GetNextToken(mathEquation);
while (token != string.Empty)
{
// Remove token from mathEquation
mathEquation = mathEquation.Remove(0, token.Length);
// If token is a grouping character, it affects program flow
if (_grouping.Contains(token))
{
switch (token)
{
case "(":
EvaluateMathString(ref mathEquation, ref numbers, index);
break;
case ")":
return;
}
}
// If token is an operator, do requested operation
if (_operators.Contains(token))
{
// If next token after operator is a parenthesis, call method recursively
string nextToken = GetNextToken(mathEquation);
if (nextToken == "(")
{
EvaluateMathString(ref mathEquation, ref numbers, index + 1);
}
// Verify that enough numbers exist in the List<double> to complete the operation
// and that the next token is either the number expected, or it was a (meaning
// that this was called recursively and that the number changed
if (numbers.Count > (index + 1) &&
(double.Parse(nextToken) == numbers[index + 1] || nextToken == "("))
{
switch (token)
{
case "+":
numbers[index] = numbers[index] + numbers[index + 1];
break;
case "-":
numbers[index] = numbers[index] - numbers[index + 1];
break;
case "*":
numbers[index] = numbers[index] * numbers[index + 1];
break;
case "/":
numbers[index] = numbers[index]/numbers[index + 1];
break;
case "%":
numbers[index] = numbers[index] % numbers[index + 1];
break;
}
numbers.RemoveAt(index + 1);
}
else
{
// Handle Error - Next token is not the expected number
throw new FormatException("Next token is not the expected number");
}
}
token = GetNextToken(mathEquation);
}
}
// Gets the next mathematical token in the equation
private static string GetNextToken(string mathEquation)
{
// If we're at the end of the equation, return string.empty
if (mathEquation == string.Empty)
{
return string.Empty;
}
// Get next operator or numeric value in equation and return it
string tmp = "";
foreach (char c in mathEquation)
{
if (_allOperators.Contains(c))
{
return (tmp == "" ? c.ToString() : tmp);
}
else
{
tmp += c;
}
}
return tmp;
}
}
하지만 솔직히,이 값은 다음 난 그냥 Loaded
이벤트의 값을 설정 거라고 하나의 형태로 사용하는 경우 보기 뒤에 코드 :)
주목할 것은 '(nextToken == "("(double.Parse (nextToken) == numbers [index + 1] || nextToken =="(")'대신에'|| double.Parse (nextToken) == numbers [index + 1] 파싱 할 때 충돌을 피하십시오. – herohuyongtao
@herohuyongtao 오, 그래야합니다. 실제로 if (nextToken == "(")'몇 줄 전에 그 체크를 대신해서 제거 할 수 있는지 확인합니다. 나는'ConverterParameter'가 유효한 수학 공식 일 것이라고 가정하고 이것을 썼습니다. 수식이 유효하지 않아 개발자가 그것에 대해 알고 수정할 수 있으면 충돌이 발생해야합니다. :) – Rachel