更新3
错误是假设人们可以通过在代码隐藏中为其名称(在 xaml 中指定)分配一个新控件来简单地替换可视树中的控件
更新2
您的错误如下。如果你写
<TextBlock Name="tb" Text="tb"/>
然后在代码中你会这样做
tb = new TextBlock() { Text = "Test" };
那么您将拥有一个新的文本块作为变量,xaml 中的任何内容都不会改变。您要么必须更改现有控件,要么删除旧控件并添加新控件。
我说的是您的标题、潜台词和描述。你不会改变它们
更新:
这里是通过指定输入掩码动态创建控件的示例:
MainWindow.xaml
<Window x:Class="WpfApplication35.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525" xmlns:local="clr-namespace:WpfApplication35">
<Grid>
<local:UserControl1 x:Name="myUserControl"/>
</Grid>
</Window>
MainWindow.cs
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
myUserControl.BuildControls("a {enter a} b {enter b1}{enter c2}");
}
}
UserControl1.xaml
<UserControl x:Class="WpfApplication35.UserControl1"
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="30" d:DesignWidth="300">
<WrapPanel Name="root" Orientation="Horizontal"/>
</UserControl>
UserControl1.cs
public partial class UserControl1 : UserControl
{
public List<CustomField> Fields = new List<CustomField>();
public UserControl1()
{
InitializeComponent();
}
public UserControl1(string mask)
{
InitializeComponent();
BuildControls(mask);
}
public void BuildControls(string mask)
{
//Parsing Input
var fields = Regex.Split(mask, @"(.*?\}\s)");
foreach (var item in fields)
{
if (item != "")
{
int index = item.IndexOf('{');
string namestring = item.Substring(0, index).Trim();
var field = new CustomField() { Name = namestring };
string valuesstring = item.Substring(index, item.Length - index).Trim();
var values = valuesstring.Split(new char[] { '{', '}' }, StringSplitOptions.RemoveEmptyEntries);
foreach (var val in values)
{
var valuewrapper = new FieldValue() { Value = val };
field.Values.Add(valuewrapper);
}
Fields.Add(field);
}
}
foreach (var field in Fields)
{
var stackPanel = new StackPanel() { Orientation = Orientation.Horizontal };
var label = new Label() { Content = field.Name, Margin = new Thickness(4) };
stackPanel.Children.Add(label);
foreach (var item in field.Values)
{
var tb = new TextBox() { Margin = new Thickness(4), Width = 200 };
tb.SetBinding(TextBox.TextProperty, new Binding() { Path = new PropertyPath("Value"), Source = item, Mode = BindingMode.TwoWay });
stackPanel.Children.Add(tb);
}
root.Children.Add(stackPanel);
}
}
}
public class CustomField
{
public string Name { get; set; }
public List<FieldValue> Values = new List<FieldValue>();
}
public class FieldValue
{
public string Value { get; set; }
}
这样字段和值将由 UserControl1 中的 Fields 集合表示。字段的值会随着用户键入内容而更新。但只有一种方式,即用户输入更新对应的Value属性,但在运行时改变Value属性不会影响对应的文本框。要实现从值到文本框的更新,您必须实现 INotifyProperty 接口
过时
既然你问了。
有数百种可能的实现方式,具体取决于您要归档什么、您希望如何验证、是否要使用 MVVM、是否要使用绑定等。通常有两种方法:创建用户控件和创建自定义控制。我相信第一个更适合你。
使用以下 xaml 创建用户控件:
<Grid Height="24">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Label Content="Size: " Grid.Column="0"/>
<TextBox Name="tbSize" Grid.Column="1"/>
<Label Content="Colour:" Grid.Column="2"/>
<TextBox Name="tbColour" Grid.Column="3"/>
</Grid>
在代码隐藏中,您可以通过名称访问 TextBox 并执行您想做的任何事情。
您可以在 xaml 和代码隐藏中使用用户控件。
在xml中:
为用户控件的命名空间指定别名(查看 xmlns:local)
<Window x:Class="WpfApplication35.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525"
xmlns:local="clr-namespace:WpfApplication35">
<Grid>
<local:UserControl1/>
</Grid>
</Window>
在代码隐藏中你可以这样使用它:
public MainWindow()
{
InitializeComponent();
var myUserControl = new UserControl1();
}
有很多话要说,这些都是基本的东西,所以请查看教程并提出问题。
附:如果您正在学习 WPF,则必须学习绑定。