Как удалить границу ButtonChrome (при определении шаблона границы)?

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

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

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

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

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

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

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

Ответ 1

Я не думаю, что есть простой способ избавиться от этой Белой границы. Фактическая подпрограмма называется 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 или установив ширину или высоту примерно на 3.99 и "Белая граница" уходит.

Обновление
Чтобы отключить внутреннюю границу ButtonChrome, вы можете создать свой собственный ButtonChrome, который добавляет это свойство. К сожалению, ButtonChrome запечатан, поэтому мы не можем наследовать его. Я попытался скопировать весь класс и добавить Property DisableInnerBorder и, похоже, работает. Вы можете использовать его так:

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

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

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

Ответ 2

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

Пример

 <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/

Ответ 3

Не следует пытаться настроить 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>

Ответ 4

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

То, что я хотел, было плоскими кнопками, которые использовали обычный хром, когда мы были перепутаны. Лучший способ, который я смог найти, - обмануть и использовать два ContentPresenters внутри Grid с двумя строками. Один контент-презентатор находится внутри обычного ButtonChrome, а один находится внутри границы. Одновременно отображается только одна строка сетки, а сеттер в триггере 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>

Ответ 5

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

<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/creating-custom-wpf-button-template-in.html

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

Ответ 6

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

Здесь можно скачать исходные коды решений.

Ответ 7

Опция также должна использовать другую библиотеку, такую ​​как telerik или xceed (также доступная для свободного коммерческого использования). В моем решении я создал класс a, полученный из 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>

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