如何根据XAML中的目标控件属性来调整ControlTemplate参数



我有两个GridSplitter,一个垂直:

<GridSplitter Grid.Column="1" ResizeDirection="Columns" VerticalAlignment="Stretch" 
              Background="Transparent" Template="{StaticResource GridSplitterTemplate}"/>

和一个横线:

<GridSplitter Grid.Row="1" ResizeDirection="Rows" HorizontalAlignment="Stretch" 
              Background="Transparent" Template="{StaticResource GridSplitterTemplate}"/>

我使用这个模板给他们想要的外观:

<Window.Resources>
    <ControlTemplate x:Key="GridSplitterTemplate" TargetType="{x:Type GridSplitter}">
        <ControlTemplate.Resources>
            <Style TargetType="Ellipse">
                <Setter Property="Fill" Value="Black"/>
                <Setter Property="Height" Value="5"/>
                <Setter Property="Width" Value="{Binding Path=ActualHeight, RelativeSource={RelativeSource Self}}"/>
                <Setter Property="Margin" Value="1,3"/>
            <!-- Or:
                <Setter Property="Margin" Value="3,1"/>
            -->
            </Style>
        </ControlTemplate.Resources>
        <Grid>
            <Grid.Style>
                <Style>
                    <Style.Triggers>
                        <Trigger Property="Grid.IsMouseOver" Value="True">
                            <Setter Property="Grid.Background" Value="DarkGray"></Setter>
                        </Trigger>
                    </Style.Triggers>
                </Style>
            </Grid.Style>
            <Rectangle Fill="#00FF00FF">
                <!-- Completely transparent, just to fill the space -->
            </Rectangle>
            <!-- Orientation="Horizontal"  if it's horizontal... -->
            <StackPanel Orientation="Vertical" VerticalAlignment="Center" HorizontalAlignment="Center">
                <!--<StackPanel.Style>
                    <Style>
                        <Style.Triggers>
                            <Trigger Property="GridSplitter.ResizeDirection" Value="Rows">
                            </Trigger>
                        </Style.Triggers>
                    </Style>
                </StackPanel.Style>-->
                <Ellipse/>
                <Ellipse/>
                <Ellipse/>
            </StackPanel>
        </Grid>
    </ControlTemplate>
</Window.Resources>

问题是该模板仅对水平GridSplitter有效。我必须复制整个模板,只是为了改变两个字段(StackPanelOrientation<Style TargetType="Ellipse">标签中的Margin值)。

是否有办法根据GridSplitterResizeDirection来调整这些模板值?

好的,使用DataTrigger s:

<ControlTemplate x:Key="GridSplitterTemplate" TargetType="{x:Type GridSplitter}">
    <ControlTemplate.Resources>
        <Style TargetType="Ellipse">
            <Setter Property="Fill" Value="Black"/>
            <Setter Property="Height" Value="5"/>
            <Setter Property="Width" Value="{Binding Path=ActualHeight, RelativeSource={RelativeSource Self}}"/>
            <!--<Setter Property="Margin" Value="3,1"/>-->
            <Style.Triggers>
                <DataTrigger Binding="{Binding ResizeDirection, RelativeSource={RelativeSource FindAncestor, AncestorType=GridSplitter}}" Value="Rows">
                    <Setter Property="Margin" Value="3,1"/>
                </DataTrigger>
                <DataTrigger Binding="{Binding ResizeDirection, RelativeSource={RelativeSource FindAncestor, AncestorType=GridSplitter}}" Value="Columns">
                    <Setter Property="Margin" Value="1,3"/>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </ControlTemplate.Resources>
    <Grid>
        <Grid.Style>
            <Style>
                <Style.Triggers>
                    <Trigger Property="Grid.IsMouseOver" Value="True">
                        <Setter Property="Grid.Background" Value="DarkGray"></Setter>
                    </Trigger>
                </Style.Triggers>
            </Style>
        </Grid.Style>
        <Rectangle Fill="#00FF00FF">
            <!-- Completely transparent, just to fill the space -->
        </Rectangle>
        <StackPanel VerticalAlignment="Center" HorizontalAlignment="Center">
            <StackPanel.Style>
                <Style>
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding ResizeDirection, RelativeSource={RelativeSource FindAncestor, AncestorType=GridSplitter}}" Value="Rows">
                            <Setter Property="StackPanel.Orientation" Value="Horizontal"/>
                        </DataTrigger>
                        <DataTrigger Binding="{Binding ResizeDirection, RelativeSource={RelativeSource FindAncestor, AncestorType=GridSplitter}}" Value="Columns">
                            <Setter Property="StackPanel.Orientation" Value="Vertical"/>
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </StackPanel.Style>
            <Ellipse/>
            <Ellipse/>
            <Ellipse/>
        </StackPanel>
    </Grid>
</ControlTemplate>

两种可能的方法:

  1. 使用IValueConverters将StackPanel的方向和边距绑定到ResizeDirection属性。
  2. 子类"GridSplitter",并为方向和边距添加新的依赖属性。

编辑 3。对于WPF来说,我没有想到的最好的方法是使用DataTrigger。

第一个选项似乎更容易。只需将orientation属性绑定到TemplatedParent -> ResizeDirection,并使用converter:

<StackPanel Orientation="{Binding RelativeSource={RelativeSource TemplatedParent},
                                  Path=ResizeDirection,
                                  Converter={StaticResource ResizeDirectionToOrientationConverter}}">

转换器应该像这样:

public class ResizeDirectionToOrientationConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var resizeDirection = value as ResizeDirection?
        if (resizeDirection.HasValue)
        {
            switch (resizeDirection.Value)
            {
                case GridResizeDirection.Columns:
                    return Orientation.Horizontal;
                case GridResizeDirection.Rows:
                    return Orientation.Vertical;
                case GridResizeDirection.Auto:
                    throw new NotImplementedException();  // todo?
            }
        }
        return DependencyProperty.UnsetValue;
    }
}

最新更新