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

时间:2014-03-12 17:39:35

标签: wpf xaml

我有两个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有效。我必须复制整个模板只是为了更改两个字段(StackPanel的{​​{1}}和Orientation标记中的Margin值。

是否有办法根据<Style TargetType="Ellipse">的{​​{1}}来调整这些模板值?

2 个答案:

答案 0 :(得分:3)

好的,使用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 :(得分:1)

两种可能的方法:

  1. 使用IValueConverters将StackPanel的方向和边距绑定到ResizeDirection属性。
  2. Subclass&#34; GridSplitter&#34;并为方向和边距添加新的依赖项属性。
  3. 编辑 3. WPF最好的一个我没有想到的 - 使用DataTrigger。

    第一种选择似乎更容易。只需将orientation属性绑定到TemplatedParent - &gt; ResizeDirection,带转换器:

    <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;
        }
    }