Вы задали несколько хороших вопросов; однако мы часто оказываемся в поиске решения, игнорируя исходную проблему. Прежде чем ответить на ваши вопросы, я хотел бы изучить ваши макетные ожидания.
В предоставленном вами коде предполагается, что у вас есть пользовательский элемент управления (customVideoControl), чей экземпляр имеет высоту 300 пикселей. Шаблон ControlTemplate, примененный к этому элементу управления, имеет 4 строки, которые вычисляют высоты на основе высоты экземпляра. На основании этих настроек ваши 4 строки будут иметь следующие значения:
Строка 0: 240
Ряд 1: 20
Ряд 2: 60
Ряд 3: 50
Суммарно до 370px, что на 70px больше, чем у контроля. Это означает, что строка 3 будет полностью скрыта от глаз, а строка 2 будет обрезана до верхних 40 пикселей. Я предполагаю, что это не ваше намерение. Если это ваше намерение, то ответы ниже, мы надеемся, помогут вам на вашем пути. Если вы хотите масштабировать высоту строк на основе соотношения, то вы можете использовать размер звезды. Ваше предлагаемое соотношение будет использовать следующие параметры:
<Grid.RowDefinitions>
<RowDefinition Height="240*"/>
<RowDefinition Height="20*"/>
<RowDefinition Height="60*"/>
<RowDefinition Height="50*"/>
</Grid.RowDefinitions>
Если вы все еще хотите измерить высоту строк, необходимо внести несколько исправлений.
Математические операции не могут быть выполнены в расширениях разметки (фигурные скобки). Ваш подход к разделению может не вызывать исключение синтаксического анализа xaml, но я сомневаюсь, что он работает правильно. Преобразователь значений необходим для достижения желаемого.
TemplateBinding - это просто облегченная версия привязки RelativeSource. Поскольку TemplateBinding является легковесным, он не допускает конвертеры.
Чтобы получить ожидаемое поведение, вам нужно использовать Binding с RelativeSource. Поэтому нужный код выглядит примерно так:
<RowDefinition Height="{Binding Path=Height,
RelativeSource={RelativeSource TemplatedParent},
Converter={StaticResource DivisionConverter},
ConverterParameter=15}"
/>
Где DivisionConverter - это ключ пользовательского конвертера. Параметр ConverterParameter в этом примере позволяет разработчику указывать знаменатель вместо создания отдельного преобразователя для каждого числа.
Вот пример пользовательского DivisionConverter, который вам нужно создать:
public class DivisionConverter : IValueConverter
{
#region IValueConverter Members
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
// Default to 0. You may want to handle divide by zero
// and other issues differently than this.
double result = 0;
// Not the best code ever, but you get the idea.
if (value != null && parameter != null)
{
try
{
double numerator = (double)value;
double denominator = double.Parse(parameter.ToString());
if (denominator != 0)
{
result = numerator / denominator;
}
else
{
// TODO: Handle divide by zero senario.
}
}
catch (Exception e)
{
// TODO: Handle casting exceptions.
}
}
return result;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
#endregion
Если вы хотите включить и деление, и вычитание в одну и ту же привязку, вам потребуется либо создать специальный преобразователь, либо использовать MultiBinding (для чего также потребуется создать специальный MultiBindingConverter).