在 wpf c# 中解决动态创建的内容
Address dynamic created content in wpf c#
我正在为学习目的创建一个动态 GUI。单击“+”按钮后,用户可以添加 itemControl 模板。
通过动态创建元素的名称(在本例中 x:Name="lblName" 应该可用但必须先构建)获取元素的最佳做法是什么?
MainWindow.xaml:
<ItemsControl Name="icDynamicTableColumn">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Margin="0,0,0,5">
<StackPanel>
<TextBlock Text="{Binding Description}" Height="23" Width="auto" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="5"/>
<TextBox x:Name="lblName" Text="{Binding Textfield}" Height="23" VerticalAlignment="Top" HorizontalAlignment="Stretch" Margin="5"/>
</StackPanel>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
MainWindow.xaml.cs:
public partial class MainWindow : Window
{
[...]
public ObservableCollection<DynamicTableColumn> items = new ObservableCollection<DynamicTableColumn>();
[...]
public MainWindow()
{
[...]
InitializeComponent();
icDynamicTableColumn.ItemsSource = items;
}
public class DynamicTableColumn
{
public string Description
{
get {
return _description;
}
set {
[...]
}
}
private string _description;
public string Textfield { get; set; }
}
}
如果在用户添加新项目或更改文本时做一些操作就足够了,我建议使用事件,例如已加载或已更改文本。
如果确实需要动态查找文本框,可以使用如下代码:
ObservableCollection<DynamicTableColumn> Collection = new ObservableCollection<DynamicTableColumn>();
public MainWindow()
{
InitializeComponent();
icDynamicTableColumn.ItemsSource = Collection;
Loaded += MainWindow_Loaded;
}
private StackPanel Panel;
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
//find the panel that contains the children
Panel = (StackPanel)VisualTreeHelper.GetChild(VisualTreeHelper.GetChild(
VisualTreeHelper.GetChild(icDynamicTableColumn, 0), 0), 0);
}
TextBox GetTextBoxForIndex(int index)
{
//get the child for a given index
var presenter = (ContentPresenter)VisualTreeHelper.GetChild(Panel, index);
return (TextBox)presenter.ContentTemplate.FindName("lblName", presenter);
}
private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
Collection.Add(new DynamicTableColumn());
//make sure that the Textbox was loaded
icDynamicTableColumn.UpdateLayout();
var textBox = GetTextBoxForIndex(Collection.Count - 1);
}
请注意,这假定您使用 ItemsControl 并且没有更改它的 (Control)Template。如果您经常需要这样做,您可以创建自己的 ItemsControl(从中派生)并公开 GetTextBoxForIndex 方法。但是,您应该进行一些安全检查(例如,必须加载范围内的索引和演示者)。
我正在为学习目的创建一个动态 GUI。单击“+”按钮后,用户可以添加 itemControl 模板。
通过动态创建元素的名称(在本例中 x:Name="lblName" 应该可用但必须先构建)获取元素的最佳做法是什么?
MainWindow.xaml:
<ItemsControl Name="icDynamicTableColumn">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Margin="0,0,0,5">
<StackPanel>
<TextBlock Text="{Binding Description}" Height="23" Width="auto" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="5"/>
<TextBox x:Name="lblName" Text="{Binding Textfield}" Height="23" VerticalAlignment="Top" HorizontalAlignment="Stretch" Margin="5"/>
</StackPanel>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
MainWindow.xaml.cs:
public partial class MainWindow : Window
{
[...]
public ObservableCollection<DynamicTableColumn> items = new ObservableCollection<DynamicTableColumn>();
[...]
public MainWindow()
{
[...]
InitializeComponent();
icDynamicTableColumn.ItemsSource = items;
}
public class DynamicTableColumn
{
public string Description
{
get {
return _description;
}
set {
[...]
}
}
private string _description;
public string Textfield { get; set; }
}
}
如果在用户添加新项目或更改文本时做一些操作就足够了,我建议使用事件,例如已加载或已更改文本。
如果确实需要动态查找文本框,可以使用如下代码:
ObservableCollection<DynamicTableColumn> Collection = new ObservableCollection<DynamicTableColumn>();
public MainWindow()
{
InitializeComponent();
icDynamicTableColumn.ItemsSource = Collection;
Loaded += MainWindow_Loaded;
}
private StackPanel Panel;
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
//find the panel that contains the children
Panel = (StackPanel)VisualTreeHelper.GetChild(VisualTreeHelper.GetChild(
VisualTreeHelper.GetChild(icDynamicTableColumn, 0), 0), 0);
}
TextBox GetTextBoxForIndex(int index)
{
//get the child for a given index
var presenter = (ContentPresenter)VisualTreeHelper.GetChild(Panel, index);
return (TextBox)presenter.ContentTemplate.FindName("lblName", presenter);
}
private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
Collection.Add(new DynamicTableColumn());
//make sure that the Textbox was loaded
icDynamicTableColumn.UpdateLayout();
var textBox = GetTextBoxForIndex(Collection.Count - 1);
}
请注意,这假定您使用 ItemsControl 并且没有更改它的 (Control)Template。如果您经常需要这样做,您可以创建自己的 ItemsControl(从中派生)并公开 GetTextBoxForIndex 方法。但是,您应该进行一些安全检查(例如,必须加载范围内的索引和演示者)。