为什么这个数据绑定不改变 GridUnitType?
Why does this data binding not change the 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 像素)。
为什么会这样,你会怎么做?
<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>
截图一:
截图二:
截图三:
Res ipsa loquitor,就我而言,但为了安全起见:
因为父级可能会调整大小,网格拆分器会更改两列之间的比例,同时为每一列保留 GridUnitType.Star
,以便在调整父级大小时,比例自然会保持不变。这保留了 XAML.
中初始宽度值的意图
左列的 Width.Value
结果与左 Border 的 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);
实际上,navigator/content 列可以交换,或者它们可以是行。这两个都是通过在作为拆分控件模板的子项的 HeaderedContentControl
上切换模板来完成的。
我的目标是保存一个 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 像素)。
为什么会这样,你会怎么做?
<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>
截图一:
截图二:
截图三:
Res ipsa loquitor,就我而言,但为了安全起见:
因为父级可能会调整大小,网格拆分器会更改两列之间的比例,同时为每一列保留 GridUnitType.Star
,以便在调整父级大小时,比例自然会保持不变。这保留了 XAML.
Width.Value
结果与左 Border 的 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);
实际上,navigator/content 列可以交换,或者它们可以是行。这两个都是通过在作为拆分控件模板的子项的 HeaderedContentControl
上切换模板来完成的。