Можем ли мы манипулировать (вычитать) значение свойства во время назначения ставок? - PullRequest
6 голосов
/ 28 апреля 2010

В настоящее время я определяю несколько сеток следующим образом:

<Grid.RowDefinitions>
   <RowDefinition Height="{TemplateBinding Height-Height/5}"/>
   <RowDefinition Height="{TemplateBinding Height/15}"/>
   <RowDefinition Height="{TemplateBinding Height/20}"/>
  <RowDefinition Height="{TemplateBinding Height/6}"/>
 </Grid.RowDefinitions>

Хотя деление работает нормально, вычитание не дает выходных данных.

Я тоже пытался так:

<RowDefinition Height="{TemplateBinding Height-(Height/5)}"/>

Все еще нет результата. Любые предложения плз.

Спасибо, Subhen

**

Обновление

** Теперь в моем XAML я попытался реализовать IvalueConverter, например:

<RowDefinition Height="{TemplateBinding Height, Converter={StaticResource heightConverter}}"/>

Добавлена ​​ссылка как

<local:medieElementHeight x:Key="heightConverter"/>

В side generic.cs я кодировал следующее:

public class medieElementHeight : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            //customVideoControl objVdeoCntrl=new customVideoControl();
            double custoMediaElementHeight = (double)value;//objVdeoCntrl.customMediaPlayer.Height;

            double mediaElementHeight = custoMediaElementHeight - (custoMediaElementHeight / 5);
            return mediaElementHeight;
        }


        #region IValueConverter Members


         object IValueConverter.ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }

        #endregion
    }

Но получается исключение Неизвестная высота элемента в элементе RowDefination.

Обновление кода @ Тони

<Style TargetType="local:customVideoControl">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="local:customVideoControl">
              <Grid>
                        <Grid.RowDefinitions>
                         <RowDefinition Height="{TemplateBinding Height-Height/5}"/>
                        <RowDefinition Height="{TemplateBinding Height/15}"/>
                       <RowDefinition Height="{TemplateBinding Height/20}"/>
                       <RowDefinition Height="{TemplateBinding Height/6}"/>
     </Grid.RowDefinitions>
                      <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="2*"/>
                          <ColumnDefinition Width="2*"/>
                          <ColumnDefinition Width="2*"/>
                      </Grid.ColumnDefinitions>
                    <MediaElement x:Name="customMediaPlayer" 
                                   Source="{TemplateBinding CustomMediaSource}"
                                   HorizontalAlignment="Center"
                                   VerticalAlignment="Center"
                                   Height="{TemplateBinding Height}"
                                   Width="{TemplateBinding Width}"
                                  Grid.Row="0" Grid.ColumnSpan="3"
                                  />
                   </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

Теперь мой реализующий XAML-файл содержит следующее:

<customMediaElement:customVideoControl x:Name="custMediaElement" Width="400" Height="300"  nextBtnEvent="custMediaElement_nextBtnEvent" prevBtnEvent="custMediaElement_prevBtnEvent" Visibility="Collapsed"/>

Теперь я хочу вычесть или разделить значения в зависимости от высоты custMediaElement.

Ответы [ 3 ]

9 голосов
/ 28 апреля 2010

Вы задали несколько хороших вопросов; однако мы часто оказываемся в поиске решения, игнорируя исходную проблему. Прежде чем ответить на ваши вопросы, я хотел бы изучить ваши макетные ожидания.

В предоставленном вами коде предполагается, что у вас есть пользовательский элемент управления (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>

Если вы все еще хотите измерить высоту строк, необходимо внести несколько исправлений.

  1. Математические операции не могут быть выполнены в расширениях разметки (фигурные скобки). Ваш подход к разделению может не вызывать исключение синтаксического анализа xaml, но я сомневаюсь, что он работает правильно. Преобразователь значений необходим для достижения желаемого.

  2. 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).

2 голосов
/ 28 апреля 2010

Вместо того, чтобы вычитать одну пятую, почему бы вам просто не умножить на 0,8?

2 голосов
/ 28 апреля 2010

Я думаю, вы должны использовать Converter для этой цели

...