Почему эта привязка данных не меняет GridUnitType?

Моя цель - сохранить GridSplitter положение для последующего отзыва. Сплиттер находится внутри Grid элемент управления с тремя столбцами, определенными следующим образом:

<Grid.ColumnDefinitions>
    <ColumnDefinition Width="{Binding GridPanelWidth, Mode=TwoWay}" />
    <ColumnDefinition Width="3" />  <!--splitter itself is in this column-->
    <ColumnDefinition Width="2*" />
</Grid.ColumnDefinitions>

Недвижимость GridPanelWidth определяется таким образом в модели представления:

private GridLength _gridPanelWidth = new GridLength(1, GridUnitType.Star);
public GridLength GridPanelWidth
{
    get { return _gridPanelWidth; }
    set
    {
        if (_gridPanelWidth != value)
            SetProperty(ref _gridPanelWidth, value, () => GridPanelWidth);
    }
}

Проблема у меня заключается в том, что при перемещении сплиттера привязка обновляет только Double (Значение) компонент связанного свойства, но не GridUnitType Часть этого.

Пример: свойство по умолчанию имеет значение 1*, Пользователь перетаскивает разделитель, и значение становится 354*вместо просто 354, При восстановлении значения оно становится огромным (354 раза, а не 354 пикселя).

Почему это происходит, и что бы вы сделали с этим?

1 ответ

Решение
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="{Binding GridPanelWidth, Mode=TwoWay}" />
        <ColumnDefinition Width="4" />
        <!--splitter itself is in this column-->
        <ColumnDefinition x:Name="RightColumn" Width="2*" />
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="*" />
        <RowDefinition Height="Auto" />
    </Grid.RowDefinitions>

    <Border
        BorderBrush="Gray"
        BorderThickness="1"
        Grid.Column="0"
        Grid.Row="0"
        />

    <GridSplitter
        Background="SteelBlue"
        ResizeBehavior="PreviousAndNext"
        ResizeDirection="Columns"
        VerticalAlignment="Stretch"
        HorizontalAlignment="Stretch"
        ShowsPreview="False"
        Grid.Column="1"
        Grid.Row="0"
        />

    <Border
        BorderBrush="Gray"
        BorderThickness="1"
        Grid.Column="2"
        Grid.Row="0"
        />

    <StackPanel
        Grid.Row="1"
        Grid.ColumnSpan="3"
        Grid.Column="0"
        >
        <TextBlock>
            <Run>GridPanelWidth: </Run>
            <Run Text="{Binding GridPanelWidth.Value, Mode=OneWay}" />
            <Run Text="{Binding GridPanelWidth.GridUnitType, Mode=OneWay}" />
        </TextBlock>
        <TextBlock>
            <Run>RightColumn.Width: </Run>
            <Run Text="{Binding Width.Value, ElementName=RightColumn, Mode=OneWay}" />
            <Run Text="{Binding Width.GridUnitType, ElementName=RightColumn, Mode=OneWay}" />
        </TextBlock>
    </StackPanel>
</Grid>

Снимок экрана 1:

Снимок экрана 2:

Снимок экрана 3:

Res ipsa loquitor, насколько я понимаю, но просто чтобы быть в безопасности:

Поскольку родительский размер может быть изменен, разделитель сетки изменяет соотношение между двумя столбцами, сохраняя при этом GridUnitType.Star для каждого из них, так что при изменении размера родителя отношение, естественно, останется постоянным. Это сохраняет намерение начальных значений ширины в XAML.

Width.Value для левой колонки оказывается идентичной левой границе ActualWidthи то же самое верно для правого столбца. Вам придется взять оба и сохранить соотношение.

Обновить

я нахожу Grid/GridSplitter немного перегружен для повседневного использования, когда все, что я хочу, это еще одна панель навигации, поэтому я недавно написал SplitterControl он имеет два свойства содержимого и устанавливает сетку и разделитель со стилем в шаблоне. Я не удосужился сделать постоянный коэффициент разделения, поэтому я сделал это только сейчас.

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

Конец бизнеса прост:

Когда размер столбца изменяется, установите флаг, чтобы заблокировать рекурсию и

PaneRatio = _PART_ContentColumn.Width.Value / _PART_NavColumn.Width.Value;

когда PaneRatio изменяется, если он не был установлен обработчиком изменения размера столбца

_PART_NavColumn.Width = new GridLength(1, GridUnitType.Star);
_PART_ContentColumn.Width = new GridLength(PaneRatio, GridUnitType.Star);

На практике столбцы навигатора / содержимого можно менять местами или вместо этого они могут быть строками. Оба из них сделаны путем переключения шаблонов на HeaderedContentControl это дочерний элемент шаблона управления разделением.

Другие вопросы по тегам