WPF: Как связать элемент управления с формулой, состоящей из нескольких свойств зависимостей? - PullRequest
2 голосов
/ 13 июня 2010

Я работаю над Expression Blend, и в настоящее время я разрабатываю собственный элемент управления, который имеет сетку с 5 строками внутри, а также имеет два свойства зависимости: «Значение» и «Максимум». Три строки имеют фиксированную высоту, и я пытаюсь установить высоту оставшихся строк на «Значение / Максимум» и «1-Значение / Максимум» соответственно. Как мне пойти и сделать это?

Когда я устанавливаю высоту на «Значение», она, кажется, реагирует, но когда я иду и устанавливаю ее на «Значение / Максимум», она перестает работать. Я все еще немного новичок в WPF, поэтому должен быть другой способ достичь того, что я собираюсь, но после поиска я не смогу найти свою проблему в другом месте.

Код:

<Grid x:Name="LayoutRoot" Width="Auto" Background="Transparent">
    <Grid.RowDefinitions>
        <RowDefinition Height="32"/>
        <RowDefinition Height="{Binding Path=(Value/Maximum), ElementName=UserControl, Mode=Default}"/>
        <RowDefinition Height="16"/>
        <RowDefinition Height="{Binding Path=(1-Value/Maximum), ElementName=UserControl, Mode=Default}"/>
        <RowDefinition Height="32"/>
    </Grid.RowDefinitions>
    (...)

Кстати, значение всегда является неотрицательным двойным меньше или равно максимуму; поэтому результатом деления будет число от 0,0 до 1,0. Я хочу "звездочку" вместо высоты строки "пиксель".

Ответы [ 2 ]

3 голосов
/ 13 июня 2010

Вам необходим MultiValueConverter .Я не уверен, что понимаю, что вы делаете, но по существу, для XAML:

<RowDefinition>
    <RowDefinition.Height>
         <MultiBinding Converter={StaticResource ...}>
             <Binding ElementName=UserControl, Path=Value ... />
             <Binding ElementName=UserControl, Path=Maximum ... />
         </MultiBinding>
    </RowDefinition.Height>
</RowDefinition>

Затем в коде вам нужно объявить класс, который реализует IMultiValueConverter, и в его Convert method, values будет содержать список вещей, которые возвращали различные нормальные Binding s (0 - верхний (значение здесь), 1 - следующий, пониженный и т. д.).Наконец, вам просто нужно добавить StaticResource вашего нового класса в XAML:

<Grid.Resources>
    <localxmlns:YourNewMultiValueConverter x:Key="Whatever" />
</Grid.Resources>

Это должно позволить вам делать то, что вы хотите.

печатать xaml без intellisenseдействительно отстой

1 голос
/ 13 июня 2010

Вот MultiValueConverter, который вы можете использовать с ответом JustABill:

public class RatioStarSizing : IMultiValueConverter
{
  public static readonly RatioStarSizing Instance = new RatioStarSizing();

  public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
  {
    return new GridLength((double)values[0] / (double)values[1], GridUnitType.Star);
  }
  public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
  {
    throw new NotImplementedException();
  }
}

Это позволит вам работать с этим XAML:

<Grid x:Name="LayoutRoot" Width="Auto" Background="Transparent">    
  <Grid.RowDefinitions>    
    <RowDefinition Height="32"/>    
    <RowDefinition>
      <RowDefinition.Height>
        <MultiBinding Converter="{x:Static RatioStarSizing}">
          <Binding ElementName="UserControl" Path="Value" />
          <Binding ElementName="UserControl" Path="Maximum" />
        </MultiBinding>
      </RowDefinition.Height>
    </RowDefinition> Height="{Binding Path=(Value/Maximum), ElementName=UserControl, Mode=Default}"/>    
    <RowDefinition Height="16"/>    
    <RowDefinition Height="*" />
    <RowDefinition Height="32"/>    
</Grid.RowDefinitions>    
(...)    

Обратите внимание на хитрый прием использования звездыразмер, чтобы избежать необходимости в двух MultiValueConverter: первый элемент установлен в звезду значения / максимума, поэтому, если значение равно 4, а максимум равно 10, преобразователь будет возвращать значение «0,4 *» как размер, что приведет к следующим фактическим значениям высоты строки.

  <Grid.RowDefinitions>    
    <RowDefinition Height="32"/>    
    <RowDefinition Height="0.4*"/>
    <RowDefinition Height="16"/>    
    <RowDefinition Height="*" />
    <RowDefinition Height="32"/>    
  </Grid.RowDefinitions>    

Как вы можете видеть, с помощью MultiValueConverter вы достигнете того, что вам нужно.

В качестве сноски я разработал библиотеку, которую планирую вскоре открыть, которая позволит мненапишите все это без конвертера:

  <Grid.RowDefinitions>    
    <RowDefinition Height="32"/>    
    <RowDefinition Height="{edf:ExpressionBinding
                             new GridLength(Value/Maximum, GridUnitType.Star)"/>
    <RowDefinition Height="16"/>    
    <RowDefinition Height="*" />
    <RowDefinition Height="32"/>    
  </Grid.RowDefinitions>    

Я добавлю сюда комментарий, как только выпущу эту библиотеку для публичного использования.

...