Как нарисовать фигуру или линии внутри кнопки WPF такого размера для элемента управления, не заставляя кнопку расширяться навсегда?

у меня был быстрый Google и быстрый взгляд вокруг StackOverflow, но не мог найти никого, кто столкнулся с этой проблемой.

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

вот мой стиль XAML для кнопки:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Style x:Key="TabCloseButtonStyle" TargetType="{x:Type Button}">
        <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
        <Setter Property="Background" Value="Transparent"/>
        <Setter Property="Content">
            <Setter.Value>
                <Grid>
                    <Line Stroke="{Binding RelativeSource={RelativeSource AncestorType=Button}, Path=Foreground}"
                            X1="0"
                            Y1="0"
                            X2="{Binding RelativeSource={RelativeSource AncestorType=Grid}, Path=ActualWidth, Mode=OneWay}"
                            Y2="{Binding RelativeSource={RelativeSource AncestorType=Grid}, Path=ActualHeight, Mode=OneWay}"/>
                    <Line Stroke="{Binding RelativeSource={RelativeSource AncestorType=Button}, Path=Foreground}"
                            X1="0"
                            Y1="{Binding RelativeSource={RelativeSource AncestorType=Grid}, Path=ActualHeight, Mode=OneWay}"
                            X2="{Binding RelativeSource={RelativeSource AncestorType=Grid}, Path=ActualWidth, Mode=OneWay}"
                            Y2="0"/>
                </Grid>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

и я создаю свою кнопку, просто как тест, Вот так:

<Window x:Class="WpfTestApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="124" Width="569">
    <Grid Background="#2b3c59">
        <StackPanel Orientation="Horizontal">

            <!-- Other controls removed for clarity -->

            <Button Style="{DynamicResource TabCloseButtonStyle}"
                    HorizontalAlignment="Center"
                    VerticalAlignment="Bottom"
                    Padding="2"
                    Margin="0, 10, 0, 0"
                    MinWidth="50"
                    MinHeight="50"></Button>
        </StackPanel>
    </Grid>
</Window>

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

теперь я могу понять, почему это происходит: линии фактически выходят на одну единицу за пределы ширины и высота сетки заставляет сетку расширяться на одну единицу, затем происходит ретрансляция, привязка данных заставляет линии перерисовываться, ad infinitum.

Итак, чтобы попытаться справиться с этим, я решил поместить a в сетку, но затем, независимо от того, что я делаю с HorizontalAlignment и VerticalAlignment, я в конечном итоге получаю как холст, так и сетку с нулевой шириной и высотой, что означает, что я не получаю свой крест, что очень раздражает. Если я привязываюсь к свойствам ActualWidth и ActualHeight кнопки я просто заканчиваю с X, который имеет верхний левый угол, центрированный по центру кнопки.

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

спасибо!

3 ответов


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

вы должны быть в состоянии получить довольно красивый, растягивающийся X с просто путь:

<Path Data="M0,0 L1,1 M0,1 L1,0" Stretch="Uniform" Stroke="Red" />

Если вы хотите масштаб С размером кнопки вместо простирания (маштаб влияет на кажущуюся ширину хода), тогда как раз используйте ViewBox


вместо привязки я бы предложил использовать свойства Stretch и Margin или Padding, как показано ниже

<Grid Margin="2">
    <Line X1="0" Y1="0" Y2="1" X2="1" Stroke="Black" Stretch="Fill" />
    <Line Y1="1" X2="1" Stroke="Black" Stretch="Fill" />
</Grid>

обновление

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

<Grid MinHeight="{TemplateBinding MinHeight}" MinWidth="{TemplateBinding MinWidth}">
    <Line X1="0" Y1="0" Y2="1" X2="1" Stroke="Black" Stretch="Fill" />
    <Line Y1="1" X2="1" Stroke="Black" Stretch="Fill" />
</Grid>

спасибо всем. Решение Роба с Viewbox получился ответ. Кнопка ведет себя отлично, даже если я удаляю MidWidth и MinHeight атрибуты из объявления кнопки в файл MainWindow.в XAML.

вот мой измененный стиль:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Style x:Key="TabCloseButtonStyle" TargetType="{x:Type Button}">
        <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
        <Setter Property="Background" Value="Transparent"/>
        <Setter Property="Content">
        <Setter.Value>
            <Grid>
                <Viewbox>
                    <Path Data="M0,0 L10,10 M0,10 L10,0"
                          Stretch="Uniform"
                          Stroke="{Binding RelativeSource={RelativeSource AncestorType=Button}, Path=Foreground, Mode=OneWay}" />
                </Viewbox>
            </Grid>
        </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

еще раз спасибо за все предложения!