Как использовать BasedOn для шаблона кнопки переключения в Generic.xaml? - PullRequest
0 голосов
/ 30 декабря 2018

wpf C # xaml

В моем Generic.xaml у меня есть много стилей формы:

  <Style x:Key="ToggleButtonStyle12" TargetType="{x:Type ToggleButton}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type ToggleButton}">
                    <Grid>
                        <Path x:Name="path1" Data="{StaticResource InsideQuarter3}" Fill="DarkOrange" Stroke="Black" />
                        <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" RecognizesAccessKey="True" 
                                          SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsMouseOver" Value="true">
                            <Setter TargetName="path1" Property = "Opacity" Value="0.4"/>
                        </Trigger>
                        <Trigger Property="IsChecked" Value="true">
                            <Trigger.EnterActions>
                                <BeginStoryboard Storyboard="{StaticResource Blink_On}"/>
                            </Trigger.EnterActions>
                            <Trigger.ExitActions>
                                <BeginStoryboard Storyboard="{StaticResource Blink_Off}"/>
                            </Trigger.ExitActions>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

Единственная разница между всеми этими кнопками переключения - это определение пути и заполнение.color.

Может ли этот стиль быть шаблонным / упрощенным таким образом, чтобы требовалось указывать только цвет Path и Fill?

Это что-то вроде:

<Style x:Key="ToggleButtonStyle12" BasedOn(??????)>
    <Setter Property = "Path" Value="InsideQuarter3"/>
    <Setter Property = "Fill" Value="DarkOrange"/>
</Style>

Спасибо за любую помощь.

Правка # 1 Ну, я думал, что у меня это есть - я был не прав,Приведенный ниже код правильно установит свойства Path Data и Fill.Однако только первый созданный ToggleButton сохраняет «MouseOver» и другие ControlTemplate.Triggers.Мне нужно ВСЕ кнопки переключения в RingControl для соблюдения их собственных триггеров.

  public static class ButtonProperties
    {
        public static Color GetMyForegroundColor(DependencyObject obj)
        {
            return (Color)obj.GetValue(MyForegroundColorProperty);
        }

        public static void SetMyForegroundColor(DependencyObject obj, Color value)
        {
            obj.SetValue(MyForegroundColorProperty, value);
        }

        // Using a DependencyProperty as the backing store for MyForegroundColor.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty MyForegroundColorProperty =
            DependencyProperty.RegisterAttached("MyForegroundColor", typeof(Color), typeof(ButtonProperties), new PropertyMetadata(Colors.Black));



        public static Geometry GetData(DependencyObject obj)
        {
            return (Geometry)obj.GetValue(DataProperty);
        }

        public static void SetData(DependencyObject obj, Geometry value)
        {
            obj.SetValue(DataProperty, value);
        }

        // Using a DependencyProperty as the backing store for Data.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty DataProperty =
            DependencyProperty.RegisterAttached("Data", typeof(Geometry), typeof(ButtonProperties), new PropertyMetadata(null));



        public static Brush GetFill(DependencyObject obj)
        {
            return (Brush)obj.GetValue(FillProperty);
        }

        public static void SetFill(DependencyObject obj, Brush value)
        {
            obj.SetValue(FillProperty, value);
        }

        // Using a DependencyProperty as the backing store for Fill.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty FillProperty =
            DependencyProperty.RegisterAttached("Fill", typeof(Brush), typeof(ButtonProperties), new PropertyMetadata(null));

    }

Generic.xaml - BaseButtonStyle

  <Style x:Key="BaseButtonStyle" TargetType="{x:Type ToggleButton}">
        <Setter Property="local:ButtonProperties.MyForegroundColor" Value="Blue"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type ToggleButton}">
                    <Grid>
                    <TextBlock Text="Some Text">
                        <TextBlock.Foreground>
                            <SolidColorBrush Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(local:ButtonProperties.MyForegroundColor)}" />
                        </TextBlock.Foreground>
                    </TextBlock>

                        <Path x:Name="path1" Data="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(local:ButtonProperties.Data)}" 
                              Fill="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(local:ButtonProperties.Fill)}" 
                              Stroke="Black"/>

                        <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" RecognizesAccessKey="True" 
                                          SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsMouseOver" Value="true">
                            <Setter TargetName="path1" Property = "Opacity" Value="0.4"/>
                        </Trigger>
                        <Trigger Property="IsChecked" Value="true">
                            <Trigger.EnterActions>
                                <BeginStoryboard Storyboard="{StaticResource Blink_On}"/>
                            </Trigger.EnterActions>
                            <Trigger.ExitActions>
                                <BeginStoryboard Storyboard="{StaticResource Blink_Off}"/>
                            </Trigger.ExitActions>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

Generic.xaml - ModifiedButtonStyle1

 <Style x:Key="ModifiedButtonStyle1" TargetType="{x:Type ToggleButton}" BasedOn="{StaticResource BaseButtonStyle}">
        <Setter Property="local:ButtonProperties.MyForegroundColor" Value="Red" />
        <Setter Property="local:ButtonProperties.Data" Value="{StaticResource Arc0}" />
        <Setter Property="local:ButtonProperties.Fill" Value="LightGreen"/>
    </Style>
    <Style x:Key="ModifiedButtonStyle2" TargetType="{x:Type ToggleButton}" BasedOn="{StaticResource BaseButtonStyle}">
        <Setter Property="local:ButtonProperties.MyForegroundColor" Value="Red" />
        <Setter Property="local:ButtonProperties.Data" Value="{StaticResource Arc45}" />
        <Setter Property="local:ButtonProperties.Fill" Value="LightPink"/>
    </Style>
    <Style x:Key="ModifiedButtonStyle3" TargetType="{x:Type ToggleButton}" BasedOn="{StaticResource BaseButtonStyle}">
        <Setter Property="local:ButtonProperties.MyForegroundColor" Value="Red" />
        <Setter Property="local:ButtonProperties.Data" Value="{StaticResource Arc90}" />
        <Setter Property="local:ButtonProperties.Fill" Value="LightCoral"/>
    </Style>

Generic.xaml - Использование ModifiedButtonStyles в пользовательском элементе управления, RingControl

 <Style TargetType="{x:Type local:RingButtons2}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:RingButtons2}">
                <Border Background="{TemplateBinding Background}"
                        BorderBrush="{TemplateBinding BorderBrush}"
                        BorderThickness="{TemplateBinding BorderThickness}">

                    <Viewbox>
                        <Grid>
                            <!--Outer Rim -->
                            <Path Data="{StaticResource OuterRim}"  Fill="Silver" Stroke="Black" />
                            <Path Data="{StaticResource OuterWheelBackground}" Fill="White" Stroke="Black" />

                            <ToggleButton x:Name="PART_Button1" Style="{StaticResource ModifiedButtonStyle1}"/>
                            <ToggleButton x:Name="PART_Button2" Style="{StaticResource ModifiedButtonStyle2}"/>
                            <ToggleButton x:Name="PART_Button3" Style="{StaticResource ModifiedButtonStyle3}"/>
  ........................................................
  </Grid>
                        </Viewbox>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

Использование RingControl2 впользовательский интерфейс:

       <w:RingButtons2/>

Может показаться, что нажатие в любом месте элемента управления RingButtons2 приводит к ответу только первой определенной кнопки-переключателя, а не какой-либо другой.

Как это исправитьчто каждая из кнопок-переключателей действует независимо от других и учитывает свои собственные триггеры контрольной таблицы?

Еще раз спасибо.

Edit # 2

После удаления определения TextBlock из BaseButtonStyle,

 <TextBlock Text="Some Text">
                        <TextBlock.Foreground>
                            <SolidColorBrush Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(local:ButtonProperties.MyForegroundColor)}" />
                        </TextBlock.Foreground>
                    </TextBlock>

ВСЕ РАБОТАЕТ!Почему это??

Спасибо.

1 Ответ

0 голосов
/ 30 декабря 2018

Если у целевого элемента управления есть свойства зависимостей, которые вы можете использовать для этих пользовательских привязок, тогда вы можете использовать TemplateBinding, вот пример:

    <Style x:Key="BaseButtonStyle" TargetType="{x:Type Button}">
        <Setter Property="Foreground" Value="Blue" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Button}">
                    <TextBlock Text="Some Text" Foreground="{TemplateBinding Foreground}" />
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

    <Style x:Key="ModifiedButtonStyle" TargetType="{x:Type Button}" BasedOn="{StaticResource BaseButtonStyle}">
        <Setter Property="Foreground" Value="Red" />
    </Style>

Который вы бы затем назвали так:

<Grid>
    <Button Style="{StaticResource ModifiedButtonStyle}" />
</Grid>

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

public static class ButtonProperties
{
    public static Color GetMyForegroundColor(DependencyObject obj)
    {
        return (Color)obj.GetValue(MyForegroundColorProperty);
    }

    public static void SetMyForegroundColor(DependencyObject obj, Color value)
    {
        obj.SetValue(MyForegroundColorProperty, value);
    }

    // Using a DependencyProperty as the backing store for MyForegroundColor.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty MyForegroundColorProperty =
        DependencyProperty.RegisterAttached("MyForegroundColor", typeof(Color), typeof(ButtonProperties), new PropertyMetadata(Colors.Black));
}

И затем вы будете ссылаться и переопределять его следующим образом в своем XAML:

<Style x:Key="BaseButtonStyle" TargetType="{x:Type Button}">
    <Setter Property="behaviors:ButtonProperties.MyForegroundColor" Value="Blue"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Button}">
                <TextBlock Text="Some Text">
                    <TextBlock.Foreground>
                        <SolidColorBrush Color="{Binding RelativeSource={RelativeSource TemplatedParent},
                            Path=(behaviors:ButtonProperties.MyForegroundColor)}" />
                    </TextBlock.Foreground>
                </TextBlock>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

<Style x:Key="ModifiedButtonStyle" TargetType="{x:Type Button}" BasedOn="{StaticResource BaseButtonStyle}">
    <Setter Property="behaviors:ButtonProperties.MyForegroundColor" Value="Red" />
</Style>

Этиболее или менее одинаковы, просто в первом случае вы используете существующие свойства, уже находящиеся внутри элемента управления (или создаете новый элемент управления, в котором они есть), тогда как во втором случае вы объявляете и присоединяете их ксуществующий контроль извне.

...