WPF标签转换为文本框

7
在WPF中展示文本标签(例如“名称”)与文本框的最佳实践是什么? 我想要在文本框上方添加一个标签“名称”,并希望有许多类似的标签/文本框。 我应该将标签/文本框对放入垂直StackPanel中吗?
是否有更简单的解决方案?
6个回答

10

这里有一个可以实现此功能的控件:

using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;

public class KeyValueControl : Control
{
    public static readonly DependencyProperty KeyProperty = DependencyProperty.Register(
        "Key",
        typeof(string),
        typeof(KeyValueControl),
        new PropertyMetadata(default(string)));

    public static readonly DependencyProperty ValueProperty = DependencyProperty.Register(
        "Value",
        typeof(object),
        typeof(KeyValueControl),
        new FrameworkPropertyMetadata
        {
            DefaultValue = null,
            BindsTwoWayByDefault = true,
            DefaultUpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged,
        });

    static KeyValueControl()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(KeyValueControl), new FrameworkPropertyMetadata(typeof(KeyValueControl)));
    }

    public string Key
    {
        get
        {
            return (string)GetValue(KeyProperty);
        }
        set
        {
            SetValue(KeyProperty, value);
        }
    }

    public object Value
    {
        get
        {
            return GetValue(ValueProperty);
        }
        set
        {
            SetValue(ValueProperty, value);
        }
    }
}

样式:

<Style TargetType="{x:Type local:KeyValueControl}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:KeyValueControl}">
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="100"/>
                        <ColumnDefinition/>
                    </Grid.ColumnDefinitions>
                    <TextBlock Text="{Binding Key, RelativeSource={RelativeSource TemplatedParent}}"/>
                    <TextBox Grid.Column="1" Text="{Binding Value, RelativeSource={RelativeSource TemplatedParent}, UpdateSourceTrigger=PropertyChanged}"/>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

用法(创建一个属性网格):

<ItemsControl>
    <customControls:KeyValueControl Key="First" Value="{Binding Value1}" />
    <customControls:KeyValueControl Key="Second" Value="{Binding Value2}" />
    <customControls:KeyValueControl Key="Last" Value="{Binding Value3}" />
    <customControls:KeyValueControl Key="Bool1" Value="{Binding Bool1}" Style="{StaticResource CheckBoxStyle}"/>
    <customControls:KeyValueControl Key="Bool2" Value="{Binding Bool2}" Style="{StaticResource CheckBoxStyle}"/>
</ItemsControl>

如果它是一个控件库,将其放入 Themes/Generic.xaml - Johan Larsson
2
这不支持基本的可访问性。使用“Label”来标记事物,而不是“TextBlock”; 并适当设置“Target”属性。 - BrainSlugs83

9

这真的取决于您未来想要如何使用这些控件。如果您想多次重复使用此类控件(甚至是动态创建它),最好创建一个UserControl并对其进行编程。然后,您可以非常简单地重复使用它(比如将其放在StackPanel上)。

LabelTextBox.xaml的代码:

<UserControl x:Class="YourProject.LabelTextBox"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="49" d:DesignWidth="314" MinHeight="49" MaxHeight="49">
    <Grid>
        <Label Content="Label" Height="28" HorizontalAlignment="Left" Name="BaseLabel" VerticalAlignment="Top" />
        <TextBox Height="23" Margin="0,26,0,0" Name="BaseTextBox" VerticalAlignment="Top" />
    </Grid>
</UserControl>

LabelTextBox.xaml.cs 代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace YourProject
{
    /// <summary>
    /// Interaction logic for LabelTextBox.xaml
    /// </summary>
    public partial class LabelTextBox : UserControl
    {
        public LabelTextBox()
        {
            InitializeComponent();
        }



        string LocalLabel = "";
        string LocalTextBox = "";

        public string Label
        {
            get { return LocalLabel; }
            set
            {
                LocalLabel = value;
                BaseLabel.Content = value;
            }
        }

        public string TextBox
        {
            get { return LocalTextBox; }
            set
            {
                LocalTextBox = value;
                BaseTextBox.Text = value;
            }
        }
    }
}

你可以使用新控件的Label和TextBox属性更改标签文本和文本框内容(在设计器的“其他”部分隐藏)。您还可以为UserControl编写附加功能。
如果您不需要经常重复使用这些控件,则其他解决方案也足够。

5
不支持绑定。 - Jacob Brewer
你没有关联标签的 Target。更多信息请参见:https://www.wpf-tutorial.com/basic-controls/the-label-control/ - BrainSlugs83

3
如果您希望具有操作此文本标签结构的灵活性,我建议将每个TextBox和Label包装在DockPanel中,并在样式中设置停靠方式,以便适用于所有标签和文本框。
因此,它会像这样:
<StackPanel>
  <StackPanel.Resources>
     <Style TargetType={x:Type Label}>
      <Setter Property="DockPanel.Dock" Value="Top"/>
     </Style>
   </StackPanel.Resources>

   <DockPanel>
     <Label></Label>
     <TextBox></TextBox>
   </DockPanel>   
  <DockPanel>
    <Label></Label>
   <TextBox></TextBox>
  </DockPanel>

 </StackPanel>

1

我通常会这样做:

<StackPanel>
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto"></ColumnDefinition>
                    <ColumnDefinition Width="*"></ColumnDefinition>
                </Grid.ColumnDefinitions>
                <Label Margin="5">Repository URL:</Label>
                <TextBox Grid.Column="1" Margin="5"></TextBox>
            </Grid>
</StackPanel>

如果您经常这样做,可以创建一个UserControl或Datatemplate。但是WPF只是一种冗长的标记语言...


0
我使用这个。
    <Style TargetType="{x:Type TextBox}">
        <Setter Property="HorizontalContentAlignment" Value="Stretch" />
        <Setter Property="VerticalContentAlignment" Value="Top" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type TextBox}">
                    <Grid HorizontalAlignment="{TemplateBinding HorizontalAlignment}" 
                          VerticalAlignment="{TemplateBinding VerticalAlignment}">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="Auto" />
                            <ColumnDefinition Width="Auto" />
                            <ColumnDefinition Width="*" />
                        </Grid.ColumnDefinitions>
                        <TextBlock x:Name="ControlLabel" Grid.Column="0"
                                   VerticalAlignment="Top" HorizontalAlignment="Left" 
                                   Text="{TemplateBinding Tag}" />
                        <Line x:Name="LineColumnLabel" Grid.Column="1" X1="0" X2="0" Y1="0" Y2="{TemplateBinding Height}"
                              Stroke="#B31C1C1C" StrokeThickness="0.5" Margin="5,0,5,0" />
                        <ScrollViewer Grid.Column="2" x:Name="PART_ContentHost"
                                IsTabStop="{TemplateBinding ScrollViewer.IsTabStop}"
                                TextElement.Foreground="{TemplateBinding Foreground}"/>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="Tag" Value="{x:Null}">
                            <Setter TargetName="ControlLabel" Property="Visibility" Value="Collapsed" />
                            <Setter TargetName="ControlLabel" Property="Margin" Value="0" />
                            <Setter TargetName="LineColumnLabel" Property="Visibility" Value="Collapsed" />
                            <Setter TargetName="LineColumnLabel" Property="Margin" Value="0" />
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

而且

<Grid>
    <TextBox Tag="The Name"/>
</Grid>

你的回答可以通过提供更多支持信息来改进。请编辑以添加进一步的细节,例如引用或文档,以便他人可以确认你的答案是正确的。您可以在帮助中心中找到有关如何编写良好答案的更多信息。 - Community

-2
创建一个名为X的类,它包含标签和文本,并实现INotifyPropertyChanged接口。创建一个ObservableCollection,这将是ListBox、ComboBox、StackPanel等控件的ItemsSource。创建一个DataTemplate,以你想要的方式显示X。

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