为什么这个 WPF 按钮会跨越整个窗口?

6
总是会扩展到与文本块一样宽。我尝试了堆栈面板、停靠面板、Width="Auto"等方法。
我该如何使扩展到其自身文本的大小(就像在HTML中一样),而不是其环境中文本的大小?
    <DockPanel HorizontalAlignment="Left">
        <Button x:Name="ButtonFavorite"
                DockPanel.Dock="Top"  
                Content="Customers" 
                Margin="10" 
                Width="Auto"
                Click="ButtonFavorite_Click">
        </Button>

        <TextBlock DockPanel.Dock="Top" Text="this is a long text which makes the button stretch across the window, if this text is just a couple words, the button will be smaller, and this drives me up the wall"  Margin="10" TextWrapping="Wrap" />

    </DockPanel>

答案:

谢谢Greg,这样做可以了。以下是完整的XAML代码,现在已经可以通过右键单击按钮来更改内容,以查看按钮是否适当地扩张和收缩。

<Window x:Class="Test3784234.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300">
    <DockPanel HorizontalAlignment="Left">
        <StackPanel DockPanel.Dock="Top" Orientation="Horizontal" >
            <Button x:Name="ButtonFavorite"
                    Padding="5"
                    Cursor="Hand" 
                    DockPanel.Dock="Top"  
                    Content="Customers" 
                    Margin="10" 
                    Click="ButtonFavorite_Click">
                <Button.ContextMenu>
                    <ContextMenu>
                        <MenuItem x:Name="menuItemReports" Header="Reports" Click="MenuItem_Click" />
                        <MenuItem x:Name="menuItemContracts" Header="Contracts" Click="MenuItem_Click"/>
                        <MenuItem x:Name="menuItemCustomers" Header="Customers" Click="MenuItem_Click" />
                        <MenuItem x:Name="menuItemDocumentation" Header="Documentation Creation Instructions" Click="MenuItem_Click" />
                        <MenuItem x:Name="menuItemEmail" Header="E-Mail" Click="MenuItem_Click" />
                    </ContextMenu>
                </Button.ContextMenu>
            </Button>

        </StackPanel>

        <TextBlock x:Name="TheMessage" DockPanel.Dock="Top" Text="Right-click the 'favorites' button to change its function." Margin="10" TextWrapping="Wrap"/>

    </DockPanel>
</Window>

有趣。这个问题说有一个比实际答案多的答案。 - Cameron MacFarland
如果有人发布然后删除一个答案,这个情况会发生。看起来像是一个不太重要的 StackOverflow 待办事项。 - Edward Tanguay
6个回答

14

你所需要做的就是设置按钮的HorizontalAlignment属性。它默认为stretch,因此填充可用空间。

<Button x:Name="ButtonFavorite"
        HorizontalAlignment="Left"
        Content="Customers" 
        Margin="10" 
        Width="Auto"
        Click="ButtonFavorite_Click">

嗯,作为一个Web开发人员,我不明白为什么按钮需要“默认拉伸以填充可用空间”。 - Edward Tanguay
2
这是一个设计决策,以便在所有文化中处理所有控件时都能保持一致。如果某些文化从右到左阅读,他们是否应该将其默认设置为左对齐?HTML是从更具美国中心主义的角度开发的。 - Bryan Anderson

8

关于您对按钮大小的烦恼,这似乎是针对设计师/开发人员工作流程中的设计师,而您显然正在处理开发人员部分。出于开发的考虑,我总是在我的App.xaml中应用一些样式来确保按钮大小更好。例如,在您的app.xaml文件中的应用程序标记中:

<Application.Resources>
  <Style TargetType="Button">
    <Setter Property="MinWidth" Value="60" />
    <Setter Property="MinHeight" Value="23" />
    <Setter Property="Margin" Value="3" />
  </Style>
</Application.Resources>

关于你的实际问题:

问题在于你的 DockPanel 会根据文本内容自动拉伸宽度,而按钮也会自然扩展以填充可用区域。如果你想要一个快速而简单的解决方案,可以尝试以下方法:

<DockPanel HorizontalAlignment="Left">
    <Button x:Name="ButtonFavorite"
            DockPanel.Dock="Top"  
            Content="Customers" 
            Margin="10" 
            Width="Auto"
            MaxWidth="100"
            Click="ButtonFavorite_Click">
    </Button>
</DockPanel>

请注意MaxWidth。如果您希望结果更具组合性,请将按钮隔离在另一个面板中。(我使用StackPanel,因为我相信其他人已经在他们的示例中使用了Grid):
<DockPanel HorizontalAlignment="Left">
    <StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
        <Button x:Name="ButtonFavorite"
            Content="Customers" 
            Margin="10" 
            Width="Auto"
            Click="ButtonFavorite_Click" />
    </StackPanel>
    <TextBlock DockPanel.Dock="Top" Text="this is a long text which makes the button stretch across the window, if this text is just a couple words, the button will be smaller, and this drives me up the wall"  Margin="10" TextWrapping="Wrap" />
</DockPanel>

在这种情况下,我喜欢使用StackPanel,因为我经常将其用于创建窗体或者说窗口右下角沿着底部的水平按钮"栏目"。


关于您的Application.Resources想法,我尝试在一个高度为10的Grid.Row中放置了一个按钮,但不幸的是,该按钮并没有扩展其MinHeight。我希望能找到一些方法,使按钮对其周围环境不那么敏感。 - Edward Tanguay
关于您的MaxWidth想法,它与仅设置宽度的问题相同,如果按钮可能被称为“应用程序创建说明”或可能被称为“帮助”,我希望按钮可以相应地调整大小。 - Edward Tanguay
1
请注意,MaxWidth是一种hack解决方案。正如您所看到的,我认为更具组合性的解决方案是使用Orientation="Horizontal"的StackPanel。 - Greg D
我不确定你在Application.Resources方面遇到了什么问题。因为没有键,这些设置应该普遍适用于所有按钮,除非按钮本身有一个优先级更高的设置。 - Greg D
你通常会应用哪些其他的App.xaml样式?无论是对于按钮还是其他元素。您愿意分享吗? - MEMark

2
您可以尝试将按钮从主面板中分离出来,放置在另一个面板中。
<DockPanel HorizontalAlignment="Left">
    <Grid DockPanel.Dock="Top">
        <Button x:Name="ButtonFavorite"
                Content="Customers" 
                Margin="10" 
                Width="Auto"
                Click="ButtonFavorite_Click">
        </Button>
    </Grid>

    <TextBlock DockPanel.Dock="Top" Text="this is a long text which makes the button stretch across the window, if this text is just a couple words, the button will be smaller, and this drives me up the wall"  Margin="10" TextWrapping="Wrap" />

</DockPanel>

0
这是一个使用网格布局与 DockPanel 的示例。想法是有2列和2行。将按钮放在单个单元格中,并使该行/列对自动调整大小。然后将文本框放入第二行,并使其跨越两列。这将基本上使右上角的单元格成为空白空间,并实现您要寻找的行为。
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto" />
        <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition />
        <RowDefinition />
    </Grid.RowDefinitions>

    <Button 
        x:Name="ButtonFavorite"
        Grid.Column="0"
        Grid.Row="0"
        Content="Customers" 
        Margin="10" 
        Width="Auto"
        Click="ButtonFavorite_Click">
    </Button>

    <TextBlock 
        Grid.Column="0"
        Grid.ColumnSpan="2"
        Grid.Row="1"
        Margin="10" 
        TextWrapping="Wrap"
        Text="this is a long text which makes the button stretch across the window, if this text is just a couple words, the button will be smaller, and this drives me up the wall" />
</Grid>

0
作为另一种方法,您可以更改按钮的模板,使其基本上包含在居中的StackPanel中。就像这样:
<Button Content="Back">
    <Button.Template>
        <ControlTemplate>
            <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
                <Button Content="{TemplateBinding Content}"></Button>
            </StackPanel>
        </ControlTemplate>
    </Button.Template>
</Button>

或者您可以在app.xaml(或任何其他存储全局样式的地方)中添加一个样式,如下所示:

<Style TargetType="{x:Type Button}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate>
                <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
                    <Button Style="{x:Null}" Content="{Binding Path=Content, RelativeSource={RelativeSource AncestorType={x:Type Button}} }" FontWeight="Bold" Padding="5"></Button>
                </StackPanel>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

请注意,在将按钮添加到全局样式中时,重要的是在模板内部包括Style="{x:Null}" 属性,否则在渲染按钮时会出现无限循环的问题。

0

你能把它们放在一个两列的网格中,其中按钮跨越一列,文本跨越两列吗?


我刚试了一下,但这与给按钮一个绝对宽度是相同的,而我不想这样做,因为内容将是动态的。 - Edward Tanguay

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接