Как привязать к данным ширину ColumnDefinition или высоту RowDefinition?
-
02-07-2019 - |
Вопрос
В соответствии с шаблоном View-Model-ViewModel для WPF я пытаюсь привязать к данным значения высоты и ширины различных определений для элементов управления сетки, чтобы я мог сохранить значения, которые пользователь устанавливает для них после использования GridSplitter.Однако обычный шаблон, похоже, не работает для этих конкретных свойств.
Примечание:Я публикую это как справочный вопрос, который публикую, поскольку Google подвел меня, и мне пришлось разобраться с этим самому.Мой собственный ответ последует.
Решение 2
Я обнаружил несколько ошибок:
- Хотя в XAML это может выглядеть как двойное значение, фактическое значение высоты или ширины *Definition представляет собой структуру GridLength.
- Все свойства GridLength доступны только для чтения, вам придется создавать новое каждый раз, когда вы его меняете.
- В отличие от любого другого свойства в WPF, для Width и Height по умолчанию не установлен режим привязки данных «TwoWay», его необходимо установить вручную.
Таким образом, я использовал следующий код:
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>
Другие советы
Создать 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}}" />
Другая возможность, поскольку вы упомянули о преобразовании между GridLength
и int
, заключается в создании IValueConverter
и использовать его при привязке к Width
. IValueConverter
s также обрабатывают двустороннюю привязку, поскольку у них есть обе ConvertTo()
и ConvertBack()
методы.
Самое простое решение — просто использовать строковые настройки для этих свойств, чтобы WPF автоматически поддерживал их с помощью GridLengthConverter без каких-либо дополнительных действий.