Как убрать рамку ButtonChrome (при определении шаблона рамки)? - PullRequest
10 голосов
/ 29 декабря 2010

Я следовал ChrisF здесь и написал простую демонстрацию .

... откройте ваш проект в Expression Blend, выберите кнопку изатем щелкните правой кнопкой мыши и выберите «Изменить шаблон> Изменить копию ..».Это скопирует существующий шаблон в тот, который вы можете изменить.Это проще, если вы создадите его в словаре ресурсов.

И я могу видеть шаблон кнопки за кадром, как показано на скриншоте ниже ( ButtonChrome в Resource).

Я хочу удалить границу белого градиента ButtonChrome и оставить все остальное в пользовательском интерфейсе кнопки без изменений .Как я могу это сделать?

пс.Чтобы упростить задачу, я использую ButtonChrome как обычный элемент управления в моем представлении.Я просматриваю свойства, но все еще не знаю, где убрать «белую» границу.

(используется ButtonChrome ) alt text

( ButtonChrome в ресурсах) alt text

Ответы [ 7 ]

16 голосов
/ 29 декабря 2010

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

Sample

 <Style x:Key="NoChromeButton" TargetType="{x:Type Button}">
        <Setter Property="Background" Value="Transparent"/>
        <Setter Property="BorderThickness" Value="1"/>
        <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
        <Setter Property="HorizontalContentAlignment" Value="Center"/>
        <Setter Property="VerticalContentAlignment" Value="Center"/>
        <Setter Property="Padding" Value="1"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Button}">
                    <Grid x:Name="Chrome" Background="{TemplateBinding Background}" SnapsToDevicePixels="true">
                        <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsEnabled" Value="false">
                            <Setter Property="Foreground" Value="#ADADAD"/>
                            <Setter Property="Opacity" TargetName="Chrome" Value="0.5"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

Проверьте это тоже http://www.designerwpf.com/2008/03/27/wpf-designers-guide-to-styles-and-templates/

Эта ссылка теперь работает: http://www.designersilverlight.com/2008/03/27/wpf-designers-guide-to-styles-and-templates/

10 голосов
/ 29 декабря 2010

Я не думаю, что есть простой способ избавиться от этой Белой Границы.Фактическая вызываемая подпрограмма - DrawInnerBorder, и она вызывается из OnRender в ButtonChrome.

protected override void OnRender(DrawingContext drawingContext)
{
    Rect bounds = new Rect(0.0, 0.0, base.ActualWidth, base.ActualHeight);
    this.DrawBackground(drawingContext, ref bounds);
    this.DrawDropShadows(drawingContext, ref bounds);
    this.DrawBorder(drawingContext, ref bounds);

    // This one draws the white Rectangle
    this.DrawInnerBorder(drawingContext, ref bounds);
}

private void DrawInnerBorder(DrawingContext dc, ref Rect bounds)
{
    if ((base.IsEnabled || this.RoundCorners) && ((bounds.Width >= 4.0) && (bounds.Height >= 4.0)))
    {
        Pen innerBorderPen = this.InnerBorderPen;
        if (innerBorderPen != null)
        {
            dc.DrawRoundedRectangle(null, innerBorderPen, new Rect(bounds.Left + 1.5, bounds.Top + 1.5, bounds.Width - 3.0, bounds.Height - 3.0), 1.75, 1.75);
        }
    }
}

Как мы видим, нет свойства отключить это.Вы можете проверить это, установив IsEnabled="False" и RoundCorners="False" на ButtonChrome или установив Width или Height на что-то вроде 3,99, и «Белая граница» исчезнет.* Чтобы отключить внутреннюю границу ButtonChrome, вы можете создать свой собственный ButtonChrome, который добавляет это свойство.К сожалению, ButtonChrome запечатан, поэтому мы не можем наследовать его.Я попытался скопировать весь класс и добавить свойство DisableInnerBorder, и это, кажется, работает.Вы можете использовать его следующим образом:

<local:MyButtonChrome ...
                      DisableInnerBorder="True">

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

По-видимому, 937 строк кода было слишком много для размещения на SO :) Я загрузил MyButtonChrome.cs здесь: http://www.mediafire.com/?wnra4qj4qt07wn6

4 голосов
/ 29 декабря 2010

Вы не должны пытаться настроить ButtonChrome.* Классы Chrome зависят от темы, то есть содержат реализацию определенной темы Windows, и вы не можете переопределить ее.Посмотрите на объявление пространства имен "Microsoft_Windows_Themes" в вашем словаре ресурсов - оно, вероятно, содержит что-то вроде PresentationFramework.Aero ...

Что вы должны сделать в своих пользовательских шаблонах, это использовать обычную Border вместо ButtonChrome и определить триггерыэто изменит его фон и т. д. при нажатии или наведении кнопки.

Вот пример:

<Style x:Key="BaseButtonStyle"
   TargetType="{x:Type ButtonBase}">
<Setter Property="FocusVisualStyle"
        Value="{StaticResource ButtonFocusVisual}" />
<Setter Property="Background"
        Value="{StaticResource ButtonNormalBackground}" />
<Setter Property="BorderBrush"
        Value="{StaticResource ButtonNormalBorder}" />
<Setter Property="BorderThickness"
        Value="1" />
<Setter Property="Foreground"
        Value="{StaticResource ButtonNormalForeground}" />
<Setter Property="HorizontalContentAlignment"
        Value="Center" />
<Setter Property="VerticalContentAlignment"
        Value="Center" />
<Setter Property="Padding"
        Value="5,2,5,2" />
<Setter Property="Template">
    <Setter.Value>
        <ControlTemplate TargetType="{x:Type ButtonBase}">
            <Border Name="Chrome"
                    Background="{TemplateBinding Background}"
                    BorderBrush="{TemplateBinding BorderBrush}"
                    BorderThickness="{TemplateBinding BorderThickness}"
                    SnapsToDevicePixels="true"
                    CornerRadius="2">
                <ContentPresenter Margin="{TemplateBinding Padding}"
                                  VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                                  HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                  RecognizesAccessKey="True"
                                  SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
            </Border>
            <ControlTemplate.Triggers>
                <Trigger Property="IsMouseOver"
                         Value="True">
                    <Setter Property="Background"
                            Value="{StaticResource ButtonHoverBackground}" />
                    <Setter Property="Foreground"
                            Value="{StaticResource ButtonHoverForeground}" />
                </Trigger>

                <Trigger Property="IsPressed"
                         Value="True">
                    <Setter Property="Background"
                            Value="{StaticResource ButtonPressedBackground}" />
                    <Setter Property="Foreground"
                            Value="{StaticResource ButtonPressedForeground}" />
                </Trigger>
                <Trigger Property="ToggleButton.IsChecked"
                         Value="True">
                    <Setter Property="Background"
                            Value="{StaticResource ButtonHoverBackground}" />
                    <Setter Property="Foreground"
                            Value="{StaticResource ButtonNormalForeground}" />
                </Trigger>
                <Trigger Property="IsEnabled"
                         Value="false">
                    <Setter Property="Foreground"
                            Value="#ADADAD" />
                </Trigger>
            </ControlTemplate.Triggers>
        </ControlTemplate>
    </Setter.Value>
</Setter>

1 голос
/ 27 февраля 2015

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

То, что я хотел, это плоские кнопки, которые использовали обычный хром при наведении.Лучший способ найти способ сделать это - использовать читы и использовать два ContentPresenter внутри Grid с двумя строками.Один предъявитель контента находится внутри обычного ButtonChrome, а другой - внутри Border.Одновременно отображается только одна строка сетки, и установщик в триггере IsMouseOver определяет, какая из них отображается.

<Window.Resources>
    <Style x:Key="ButtonFocusVisual">
        <Setter Property="Control.Template">
            <Setter.Value>
                <ControlTemplate>
                    <Rectangle StrokeDashArray="1 2" StrokeThickness="1" Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" SnapsToDevicePixels="true" Margin="2"/>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    <LinearGradientBrush x:Key="ButtonNormalBackground" EndPoint="0,1" StartPoint="0,0">
        <GradientStop Color="#F3F3F3" Offset="0"/>
        <GradientStop Color="#EBEBEB" Offset="0.5"/>
        <GradientStop Color="#DDDDDD" Offset="0.5"/>
        <GradientStop Color="#CDCDCD" Offset="1"/>
    </LinearGradientBrush>
    <SolidColorBrush x:Key="ButtonNormalBorder" Color="Transparent"/>
    <Style x:Key="ActionButtonStyle" TargetType="{x:Type Button}">
        <Setter Property="FocusVisualStyle" Value="{StaticResource ButtonFocusVisual}"/>
        <Setter Property="Background" Value="{x:Null}"/>
        <Setter Property="BorderBrush" Value="{x:Null}"/>
        <Setter Property="BorderThickness" Value="0"/>
        <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
        <Setter Property="HorizontalContentAlignment" Value="Center"/>
        <Setter Property="VerticalContentAlignment" Value="Center"/>
        <Setter Property="Padding" Value="1"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Button}">
                    <Grid>
                        <Grid.RowDefinitions>
                            <RowDefinition  x:Name="ContentWithChrome" Height="0"></RowDefinition>
                            <RowDefinition  x:Name="ContentWithBorder" Height="Auto"></RowDefinition>
                        </Grid.RowDefinitions>
                        <Themes:ButtonChrome Grid.Row="0" x:Name="Chrome" BorderBrush="{TemplateBinding BorderBrush}" Background="{TemplateBinding Background}" RenderMouseOver="{TemplateBinding IsMouseOver}" RenderPressed="{TemplateBinding IsPressed}" RenderDefaulted="{TemplateBinding IsDefaulted}" SnapsToDevicePixels="true">
                            <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                        </Themes:ButtonChrome>
                        <Border Grid.Row="1" Margin="0,2,0,2">
                            <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                        </Border>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter Property="Height" TargetName="ContentWithChrome" Value="Auto" />
                            <Setter Property="Height" TargetName="ContentWithBorder" Value="0" />
                        </Trigger>
                        <Trigger Property="IsKeyboardFocused" Value="true">
                            <Setter Property="RenderDefaulted" TargetName="Chrome" Value="true"/>
                        </Trigger>
                        <Trigger Property="ToggleButton.IsChecked" Value="true">
                            <Setter Property="RenderPressed" TargetName="Chrome" Value="true"/>
                        </Trigger>
                        <Trigger Property="IsEnabled" Value="false">
                            <Setter Property="Foreground" Value="#ADADAD"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</Window.Resources>
0 голосов
/ 11 февраля 2017

Также можно использовать другую библиотеку, такую ​​как telerik или xceed (также доступна для бесплатного коммерческого использования).В своем решении я создал класс, производный от Xceed.Wpf.Toolkit.Chromes.ButtonChrome (Microsoft ButtonChrome запечатан).В моем ResourceDictionary я реализовал стиль для Combobox, созданный Blend для VS.В шаблоне ControlTemplate для ToggleButton я реализовал следующий код:

<ControlTemplate TargetType="{x:Type ToggleButton}">
    <p:ButtonChromeManaged x:Name="Chrome"
                           Width="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}"
                           Background="Transparent"
                           BorderBrush="Transparent"
                           CornerRadius="0"
                           SnapsToDevicePixels="true">
        <p:ButtonChromeManaged.Template>
            <ControlTemplate TargetType="{x:Type p:ButtonChromeManaged}">
                <Border Background="Red">
                    <Path x:Name="Arrow"
                          Margin="0,1,0,0"
                          HorizontalAlignment="Center"
                          VerticalAlignment="Center"
                          Data="{StaticResource DownArrowGeometry}"
                          Fill="Black" />
                </Border>
            </ControlTemplate>
        </p:ButtonChromeManaged.Template>

Здесь вы можете увидеть только самый непонятный материал.Ваша DownArrowGeometry и так далее, вы знаете, чтобы сделать.Я надеюсь, что это может кому-то помочь; -)

0 голосов
/ 01 января 2011

После некоторого обсуждения с Миликом, наконец, я получил окончательное решение для моего вопроса! Спасибо, Мелеак!

Вы можете скачать исходные коды решения здесь .

0 голосов
/ 29 декабря 2010

если вы хотите просто избежать WhiteBorder, вам нужно просто изменить BorderBrush = Transparent

<Microsoft_Windows_Themes:ButtonChrome x:Name="Chrome" SnapsToDevicePixels="true" 
                        Background="{TemplateBinding Background}" BorderBrush="Transparent"
                         RenderDefaulted="{TemplateBinding IsDefaulted}" RenderMouseOver="{TemplateBinding IsMouseOver}"
                          RenderPressed="{TemplateBinding IsPressed}">
                            <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" RecognizesAccessKey="True"/>
                        </Microsoft_Windows_Themes:ButtonChrome>

Если вы хотите изменить некоторые другие вещи, вам нужно создать свой собственный ControlTemplate

пожалуйста, эту ссылку

http://mark -dot-net.blogspot.com / 2007/07 / создание-заказ МОФ-кнопка-шаблон-in.html

здесь у них разные шаблоны кнопок

...