Как нарисовать фигуру или линии внутри кнопки WPF такого размера для элемента управления, чтобы кнопка не расширялась вечно? - PullRequest
7 голосов
/ 05 ноября 2010

У меня был быстрый 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>

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

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

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

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

Спасибо!

Ответы [ 3 ]

15 голосов
/ 06 ноября 2010

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

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

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

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

2 голосов
/ 06 ноября 2010

Вместо привязки я бы предложил использовать свойства 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>
0 голосов
/ 08 ноября 2010

Спасибо всем.Решение Роба с Viewbox оказалось ответом.Кнопка работает отлично, даже если я удаляю атрибуты MidWidth и MinHeight из объявления Button в 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>

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

...