由于我需要在文本框中对屏蔽输入进行排序,因此我决定构建自己的控件来处理它。
许多模板中的一个可以是"尺寸{输入尺寸}颜色{输入颜色}"我已经分解来创建一系列控件。扩展名为StackPanel
CustomTextBox
的自定义控件会从构造函数生成以下内容。
// Pseudo
Children = {
Label = { Content = "Size" },
TextBox = { Text = "enter size" },
Label = { Content = "Colour" },
TextBox = { Text = "enter colour" }
// .. and an arbitrary amount of more Labels and TextBoxes in no particular order
}
到目前为止一切顺利。但是当我希望它呈现时......那是我头痛开始的地方。
我已尝试将控件添加到父级本身的Children
属性和Measure/Arrange
以及所有Children
。 ActualHeight
和ActualWidth
会更改为0
以外的内容,但他们无法呈现/显示/变得可见。
我还尝试使用ItemsControl
并将控件添加到ItemsSource
属性中无效。
我试图在所有东西上预定义尺寸,为背景涂上红色和所有颜色,但难以捉摸的控制仍然被抓住并绑在我的屏幕上。
必须是一个巨大的"哦..."在这里,我无法找到。我拒绝相信这无法做到。我的意思是,它是WPF。 WPF太棒了。
修改更新了我目前最有可能工作的内容 - 但仍然没有。
无论我在设计师身上做了什么,但我在CustomTextBox
做的任何事情都没有显示出来。
修改 新标题更适合问题。
另外,我发现了几个以编程方式添加控件的示例。以this article为例。我没有看到我的场景和他们的场景之间的区别,除了他们的工作和按钮是可见的。
答案 0 :(得分:0)
<强> UPDATE3 强>
错误是假设,人们可以通过在代码中为控件的名称(在xaml中指定)指定一个新控件来简单地替换可视树中的控件
<强> Updated2 强>
你的错误在追随。如果你写
<TextBlock Name="tb" Text="tb"/>
然后在代码中你会做
tb = new TextBlock() { Text = "Test" };
然后你会有一个新的文本块作为变量,xaml中的任何内容都不会改变。您必须更改现有控件,或删除旧控件并添加新控件。
我在谈论你的标题,潜台词和&amp;描述。你没有改变它们
<强>更新强>
以下是通过指定输入掩码动态创建控件的示例:
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属性不会影响相应的文本框。要实现从Value到文本框的更新,您必须实现INotifyProperty接口
过时
既然你问过。 有几百种可能的实现,取决于你想要实现的目标,你想要如何验证,你想使用MVVM,你想使用绑定等吗?通常有两种方法:创建usercontrol和创建自定义控制。我相信第一个更适合你。
使用以下xaml创建一个usercontrol:
<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>
在代码隐藏中,您可以按名称访问TextBoxes并执行您想要执行的操作。
您可以在xaml和codebehind中使用usercontrol。 在xaml:
指定usercontrol命名空间的别名(查看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();
}
有很多话要说,这些都是基本的东西,所以请查看教程并提出问题。
P.S。如果您正在学习WPF,则必须学习绑定。