限制GridSplitter(MVVM)

时间:2016-04-27 13:24:18

标签: c# wpf mvvm gridsplitter

简单的情况,当我想限制GridSplitter最大值时,我可以创建不可见控件(仅参与布局),调整其Margin并使用限制网格列/行定义:

<Grid x:Name="limiter" Margin="10,10,20,10" />
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="{Binding StoreWidth, Converter={local:DoubleToGridLengthConverter}, Mode=TwoWay}"
             MaxWidth="{Binding ActualWidth, ElementName=gridLimit}" /> <!-- limit maximum -->
    ...
    </Grid.ColumnDefinitions>
    <GridSplitter ... />
    ...
</Grid>

现在复杂的情况:GridSplitter的嵌套视图,必须受到父视图的一些布局逻辑的限制。

我该怎么做?我正在寻找一个舒适的和可重复使用的解决方案。

目前我正在做复杂的方式:

  • 将属性添加到父虚拟机以绑定limiter值(例如ActualWidth);
  • 添加到嵌套的VM属性Parent;
  • 将父VM实例传递给嵌套的实例(使用属性初始化程序);
  • 现在可以使用GridSplitter绑定来限制Parent.SplitterMaxWidth

对于这个问题,有什么好的和MVVM友好的方法吗?

1 个答案:

答案 0 :(得分:0)

对于GridSplitter必须由父级限制的情况(TBH我的所有布局都可以转换为确保这一点),可以绑定到该父级并使用通用转换器来更改值。如果父母难以到达,那么制作一个简单的自定义控件:

public class GridLimiter: Grid { }

可用于标记 RelativeSource.FindAncestor轻松访问该容器:

<local:GridLimiter ... >
    ... <!-- deeply nested -->
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition MaxWidth="{Binding ActualWidth, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:GridLimiter}}}" />
            ...
        </Grid.ColumnDefinitions>
        <GridSplitter ... />
    </Grid>
    ...

此外,制作一个简单的标记扩展转换器:

public class ValueAddConverter : MarkupExtension, IValueConverter
{
    public ValueAddConverter() { }

    public override object ProvideValue(IServiceProvider serviceProvider) => this;

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) =>
        (double)value + double.Parse((string)parameter, NumberFormatInfo.InvariantInfo);

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

允许定义偏移而无需创建不可见限制器:

MaxWidth="{Binding ActualWidth, Converter={local:ValueAddConverter}, ConverterParameter=-30, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:GridLimiter}}}"