首页 文章

如何在WPF按钮内绘制尺寸为控件的形状或线条,而不会使按钮永远展开?

提问于
浏览
7

我有一个快速的谷歌,并快速浏览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 回答

  • 0

    你不应该只是为了做布局而使用绑定 . 正如您所见,绑定和布局系统不能协同工作(我认为数据绑定优先于布局,但在您的情况下,布局会导致另一个数据绑定)

    你应该能够通过一个路径获得相当漂亮,可伸缩的X:

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

    如果你想用按钮大小而不是拉伸来缩放(缩放影响明显的笔划宽度),那么只需使用 ViewBox

  • 15

    我建议使用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>
    

    Update

    所以你的例子的问题似乎是最小高度和宽度 . 如果你不能只使用高度和宽度,我建议如下

    <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>
    
  • 2

    感谢大家 . 事实上,Rob的_1510961解决方案就是答案 . 即使我从MainWindow.xaml中的Button声明中删除 MidWidthMinHeight 属性,该按钮也表现完美 .

    这是我修改后的风格:

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

    再次感谢所有的建议!

相关问题