В рамках шаблона View-Model-ViewModel для WPF я пытаюсь привязать высоту и ширину различных определений для элементов управления сеткой, поэтому я могу сохранить значения, которые пользователь устанавливает для них после использования GridSplitter. Однако нормальный шаблон, похоже, не работает для этих конкретных свойств.
Примечание: я публикую это как справочный вопрос, который я публикую, поскольку Google подвел меня, и мне пришлось решить это самостоятельно. Мой собственный ответ, чтобы следовать.
Я обнаружил ряд ошибок:
Таким образом, я использовал следующий код:
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>
Я думаю, что вера «нет WPF в ViewModel» неверна, поскольку WPF имеет множество конструкций, относящихся к шаблону MVVM, например, саму привязку данных. Вместо этого вы могли бы сказать «GridLength специфична для ВИДА» (если только это не является частью проблемы предметной области, например, в приложениях визуализации данных, чьей целью является компоновка и отображение вещей). Но уверен, что это спорный ...
@heltonbiker "GridLength относится к ВИДУ" является более точным. если ваша бизнес-логика полностью или частично не связана с макетом (дизайном) пользовательского интерфейса.
Другая возможность, поскольку вы подняли преобразование между GridLength
и int
, - это создать IValueConverter
и использовать его при привязке к Width
. IValueConverter
также обрабатывает двустороннюю привязку, поскольку у них есть методы ConvertTo()
и ConvertBack()
.
Создайте 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}}" />
Если вы ищете решение очень похожей проблемы, вы можете найти его здесь: stackoverflow.com/questions/7660967/…
В Wpf уже есть класс GridLengthConverter. Можно ли было бы использовать его как есть?
@heltonbiker К сожалению, GridLengthConverter реализует ITypeConverter, а не IValueConverter, и поэтому не может использоваться в качестве преобразования привязки WPF.
Самое простое решение - просто использовать строковые настройки для этих свойств, чтобы WPF автоматически поддерживал их с помощью GridLengthConverter без дополнительной работы.
GridLength специфичен для WPF, поэтому не относится к уровню ViewModel.