2008-09-29 2 views
28

В шаблоне View-Model-ViewModel для WPF я пытаюсь привязать высоты и ширины различных определений для элементов управления сеткой, поэтому я могу сохранить значения, которые пользователь устанавливает для них после использования GridSplitter. Однако нормальный шаблон, похоже, не работает для этих конкретных свойств.Как мне привязать ширину столбца ColumnDefinition или высоту RowDefinition?

Примечание: Я размещаю это как справочный вопрос, который я отправляю, поскольку Google сбил меня с толку, и мне пришлось самому это проработать. Мой собственный ответ.

ответ

17

Существовали ряд подводных камней я обнаружил:

  1. Хотя это может выглядеть как двойной в XAML, фактическое значение высоты ОПРЕДЕЛЕНИЮ * или ширина является структура «GridLength».
  2. Все свойства GridLength доступны только для чтения, вы должны создавать новый каждый раз, когда вы его изменяете.
  3. В отличие от любого другого свойства в WPF, ширина и высота не изменяют режим привязки данных к «TwoWay», вам необходимо вручную установить это.

Thusly, я использовал следующий код:

private GridLength myHorizontalInputRegionSize = new GridLength(0, GridUnitType.Auto) 
public GridLength HorizontalInputRegionSize 
{ 
    get 
    { 
     // If not yet set, get the starting value from the DataModel 
     if (myHorizontalInputRegionSize.IsAuto) 
      myHorizontalInputRegionSize = new GridLength(ConnectionTabDefaultUIOptions.HorizontalInputRegionSize, GridUnitType.Pixel); 
     return myHorizontalInputRegionSize; 
    } 
    set 
    { 
     myHorizontalInputRegionSize = value; 
     if (ConnectionTabDefaultUIOptions.HorizontalInputRegionSize != myHorizontalInputRegionSize.Value) 
     { 
      // Set the value in the DataModel 
      ConnectionTabDefaultUIOptions.HorizontalInputRegionSize = value.Value; 
     } 
     OnPropertyChanged("HorizontalInputRegionSize"); 
    } 
} 

И в XAML:

<Grid.RowDefinitions> 
    <RowDefinition Height="*" MinHeight="100" /> 
    <RowDefinition Height="Auto" /> 
    <RowDefinition Height="{Binding Path=HorizontalInputRegionSize,Mode=TwoWay}" MinHeight="50" /> 
</Grid.RowDefinitions> 
+9

GridLength специфичен для WPF, поэтому не относится к слою ViewModel. – 2011-09-09 07:33:40

+2

Я думаю, что вера «нет WPF в ViewModel» неверна, поскольку WPF имеет много конструкций в отношении шаблона MVVM, такого как сама привязка данных. Вместо этого вы можете сказать, что «GridLength является специфическим для VIEW» (если только это не является частью проблемы с доменом, например, в приложениях для визуализации данных, чья основная задача - компоновка и отображение вещей). Но уверен, что это противоречиво ... – heltonbiker 2014-01-17 18:24:40

4

Другая возможность, так как вы воспитывали преобразование между GridLength и int, чтобы создать IValueConverter и использовать его при привязке к Width. IValueConverter s также обрабатывают двустороннее связывание, потому что они имеют как методы ConvertTo(), так и ConvertBack().

34

Создать IValueConverter следующим образом:

public class GridLengthConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     double val = (double)value; 
     GridLength gridLength = new GridLength(val); 

     return gridLength; 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     GridLength val = (GridLength)value; 

     return val.Value; 
    } 
} 

Вы можете использовать конвертер в вашем Переплет:

<UserControl.Resources> 
    <local:GridLengthConverter x:Key="gridLengthConverter" /> 
</UserControl.Resources> 
... 
<ColumnDefinition Width="{Binding Path=LeftPanelWidth, 
            Mode=TwoWay, 
            Converter={StaticResource gridLengthConverter}}" /> 
2

Самым простым решением является просто использовать настройки строки для этих свойств, так что WPF будет автоматически поддерживают их с помощью GridLengthConverter без дополнительной работы.

Смежные вопросы