C# 以编程方式创建的控件不呈现
由于需要在文本框中对掩码输入进行排序,我决定构造自己的控件来处理这个问题 许多模板中的一个可以是Size{enter Size}color{enter color},我将其分解以创建一系列控件。扩展StackPanel(我命名为CustomTextBox)的自定义控件从构造函数生成以下内容C# 以编程方式创建的控件不呈现,c#,wpf,wpf-controls,C#,Wpf,Wpf Controls,由于需要在文本框中对掩码输入进行排序,我决定构造自己的控件来处理这个问题 许多模板中的一个可以是Size{enter Size}color{enter color},我将其分解以创建一系列控件。扩展StackPanel(我命名为CustomTextBox)的自定义控件从构造函数生成以下内容 // Pseudo Children = { Label = { Content = "Size" }, TextBox = { Text = "enter size" }, Labe
// 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属性,并对父对象、其本身和所有子对象进行测量/排列。ActualHeight和ActualWidth确实会更改为0以外的值,但它们不会呈现/显示/变得可见
我还尝试使用ItemsControl并将这些控件添加到ItemsSource属性,但没有成功
我已经尝试过在所有东西上预先定义大小,把背景涂成红色等等,但是那些难以捉摸的控件仍然需要捕捉并绑定到我的屏幕上
一定会有一个巨大的哦哦。。。这就是我找不到的。我不相信这是不可能的。我是说,这是WPF。WPF太棒了
编辑更新到我目前拥有的似乎最有可能工作的内容-但仍然没有
我在设计器中所做的一切都会显示出来,但在CustomTextBox中所做的一切都不会产生任何明显的差异
编辑
更符合问题的新标题
此外,我还发现了几个以编程方式添加控件的示例。比如说。我看不到我的场景和他们的场景之间的区别,只是他们的工作和按钮是可见的。更新3
错误在于,我们可以简单地通过在codebehind中为xaml中指定的控件名称分配一个新控件来替换可视化树中的控件
更新的2
你的错误就在后面。如果你写信
<TextBlock Name="tb" Text="tb"/>
然后您将有一个新的textblock作为变量,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>
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>
有很多话要说,这些都是基本的东西,所以检查教程并提出问题
另外,如果你正在学习WPF,那么必须学习绑定。有什么好的理由不创建一个简单的用户控件吗?@Clemens目前最好的理由是,当掩码是任意的时,我想不出一种方法来实现我想要的。没有必要重写任何东西。只需将控件添加到面板,例如UserControl中的顶级水平StackPanel。还不清楚您谈论的是哪个ItemsSource属性。您是否在任何地方使用ItemsControl?如果看不到一些代码,就很难判断哪里出了问题。@Heki ItemsSource属性用于数据,而不是视觉元素。您可以创建一个usercontrol并删除带有标签的文本框,然后在代码隐藏中处理逻辑。不需要实现从继承的自定义控件ItemsControl@netaholic但这并不能解释StackPanel的问题。但是谢谢你的澄清。好吧,这一切都很好,但它没有涵盖需求的动态部分。我不知道我是否只需要一个标签,一个文本框或者十七对和两个额外的。它确实显示了我的UserControl中的所有控件,但我以编程方式添加的所有控件都不会显示。@Heki我不清楚您的要求。你能准确地描述一下你想要记录的行为吗?当我们在同一页时,我会更新这个问题。所以,我需要能够基于一些输入配置一个输入字段,比如a{bla}b{bla}{bla},但它实际上可以是任何东西。我需要允许用户只编辑{}中的任何内容。有道理吗?@Heki,有道理。现在我明白为什么要使用ItemsControl了。我会更新一下我的答案later@Heki你觉得我的回答有用吗?还有什么我能做的吗?
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
myUserControl.BuildControls("a {enter a} b {enter b1}{enter c2}");
}
}
<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>
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; }
}
<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>
<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();
}