wpf 从后面的代码向堆栈面板添加控件(在 xaml 中定义)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12189874/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Add a control (defined in xaml) to a Stack Panel from Code behind
提问by Shankar Raju
I have a user control which I want to define as a template in XAML. In code behind, during runtime, I want to keep adding items (of type my user control) to a Stack Panel.
我有一个用户控件,我想将其定义为 XAML 中的模板。在后面的代码中,在运行时,我想继续向堆栈面板添加项目(属于我的用户控件类型)。
How would I do this?
我该怎么做?
I don't want to do this:
我不想这样做:
myUserControl myUserControl = new MyUserControl;
myStackPanel.Children.Add(myUserControl);
This is because I have set multiple properties for my UserControl in XAML and I do not want to set all bindings from code behind. I am looking for a more elegant solution.
这是因为我在 XAML 中为我的 UserControl 设置了多个属性,并且我不想从后面的代码中设置所有绑定。我正在寻找更优雅的解决方案。
How to I define my template for the User Control in XAML? How do I then do something like this?
如何在 XAML 中为用户控件定义模板?那我该怎么做呢?
myStackPanel.Children.Add(myCustomControlTemplate);
I am new to WPF, so please bear with me if this is a very trivial question.
我是 WPF 的新手,所以如果这是一个非常微不足道的问题,请耐心等待。
EDIT:(As per Erno's request)
编辑:(根据 Erno 的要求)
XAML file:
XAML 文件:
<someNamespace:MyUserControl x:Name="usrControl" SomeState="{Binding CachedValue}" MyUserControlEventAggregator="{Binding ParentEventAggregator}"
DepedencyProperty1="{Binding Property1, Mode=TwoWay}"
DepedencyProperty2="{Binding Property2}"
DepedencyProperty3="{Binding Property3}"
d:DataContext="{Binding Path=ParentViewModel}">
XAML.CS file:
XAML.CS 文件:
public partial class ParentControl: Window
{
public ParentControlViewModel ParentViewModel{ get; set; }
public ListBuilderView(ParentViewModel viewModelPassedByPRISM)
{
ParentViewModel = viewModelPassedByPRISM;
DataContext = ParentViewModel;
InitializeComponent();
}
private void AddMyUserControlButton_Click(object sender, RoutedEventArgs e)
{
// I need to create an instance of MyUserControl here and add it to any WPF component of ParentControl as I may need it for some other user action
}
private void ProcessInfoButton_Click(object sender, RoutedEventArgs e)
{
// I need to loop through and look into each of the MyUserControls that the user adds, get some values from the MyUserControl and pass this information to do some calc and make some database calls
}
}
ParentViewModel.cs file:
ParentViewModel.cs 文件:
public class ParentViewModel: BaseViewModel
{
public IEventAggregator ChildEventAggregator { get; set; }
private AnyType _property1;
public AnyType Property1
{
get { return _property1; }
set
{
_property1 = value;
NotifyPropertyChanged("Property1");
}
}
private AnyType _property2;
public AnyType Property2
{
get { return _property2; }
set
{
_property2 = value;
NotifyPropertyChanged("Property2");
}
}
private AnyType _property3;
public AnyType Property3
{
get { return _property3; }
set
{
_property3 = value;
NotifyPropertyChanged("Property3");
}
}
public AnyType CachedValue { get; set; }
}
So, as you can see all the objects of type MyUserControl that I create in xaml.cs file will share common property and update themselves. Users will interact with those controls and when they request for some processing, I have to look into each MyUserControl that user adds to the Main Control, call some methods in MyUserControl to get some info, use these info from each MyUserControl for some other processing and querying the database.
因此,如您所见,我在 xaml.cs 文件中创建的所有 MyUserControl 类型的对象将共享公共属性并自行更新。用户将与这些控件进行交互,当他们请求进行某些处理时,我必须查看用户添加到主控件中的每个 MyUserControl,调用 MyUserControl 中的一些方法来获取一些信息,将每个 MyUserControl 中的这些信息用于其他一些处理和查询数据库。
I hope this helps..
我希望这有帮助..
采纳答案by Erno
EDIT
编辑
Note that the ViewModel properties in the code you posted are collections! You might want to change those List's to ObservableCollection's.
请注意,您发布的代码中的 ViewModel 属性是集合!您可能希望将这些 List 更改为 ObservableCollection 的。
To bind to these: use an itemscontrol such as the ListBox IN THE USERCONTROL. (BTW: please use better property names!)
要绑定到这些:使用一个项目控件,例如 USERCONTROL 中的 ListBox。(顺便说一句:请使用更好的属性名称!)
Here is what it would look like:
这是它的样子:
<StackPanel>
<MyUserControl DataContext="{Binding Property1}"/>
<MyUserControl DataContext="{Binding Property2}"/>
<MyUserControl DataContext="{Binding Property3}"/>
</StackPanel>
In the MyUserControl:
在 MyUserControl 中:
<UserControl x:Class="MyUserControl">
<ListBox ItemsSource="{Binding}">
<ListBox.ItemTemplate>
? ? ? ? ? <DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding AttributeName}"/>
<TextBox Text="{Binding AttributeValue}"/>
</StackPanel>
</DataTemplate>
? ? ? ? </ListBox.ItemTemplate>
</ListBox>
</UserControl>
Old answers- Still validIn response to your comments:
旧答案 - 仍然有效回应您的评论:
You need a different approach that is very similar. By using an ItemsControl such as the ListBox you only need to specify the collection you want to bind to and automatically for each item in the collection an instance of the ItemTemplate (containing the usercontrol in this case) will be created and its DataContext will be set to the item so the bindings in the user control will be relative to an item.?
您需要一种非常相似的不同方法。通过使用 ItemsControl(例如 ListBox),您只需要指定要绑定到的集合,并且会自动为集合中的每个项目创建 ItemTemplate(在本例中包含用户控件)的实例并设置其 DataContext到项目,因此用户控件中的绑定将与项目相关。?
There is no need to add the instances in code nor to set the DataContext of each control.? Welcome to the wonderful world of data binding.
不需要在代码中添加实例,也不需要设置每个控件的DataContext。?欢迎来到数据绑定的美妙世界。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
My guess is that you are not looking for a Template but for a Style:
我的猜测是,您不是在寻找模板,而是在寻找样式:
<StackPanel x:Name="MyStackPanel">
<StackPanel.Resources>
<Style x:Key="ucStyle" TargetType="MyUserControl">
<Setter Property="Background" Value="Azure" />
<Setter Property="BorderThickness" Value="2" />
</Style>
</StackPanel.Resources>
</StackPanel>
In code:
在代码中:
myUserControl myUserControl = new MyUserControl;
Style style = MyStackPanel.FindResource("ucStyle") as Style;
if(style != null)
{
myUserControl.Style = style;
}
myStackPanel.Children.Add(myUserControl);
Or, shorter, but less obvious, using implicit styles:
或者,更短但不太明显,使用隐式样式:
<StackPanel x:Name="MyStackPanel">
<StackPanel.Resources>
<Style TargetType="MyUserControl">
<Setter Property="Background" Value="Azure" />
<Setter Property="BorderThickness" Value="2" />
</Style>
</StackPanel.Resources>
</StackPanel>
In code:
在代码中:
myUserControl myUserControl = new MyUserControl;
myStackPanel.Children.Add(myUserControl);

