从Code后面添加一个控件(在xaml中定义)到Stack Panel

时间:2012-08-30 04:26:32

标签: c# wpf xaml stackpanel

我有一个用户控件,我想在XAML中定义为模板。在后面的代码中,在运行时,我想继续添加项目(我的用户控件类型)到堆栈面板。

我该怎么做?

我不想这样做:

myUserControl myUserControl = new MyUserControl;
myStackPanel.Children.Add(myUserControl);

这是因为我在XAML中为我的UserControl设置了多个属性,我不想从后面的代码中设置所有绑定。我正在寻找更优雅的解决方案。

如何在XAML中为用户控件定义模板? 我怎么做这样的事情?

myStackPanel.Children.Add(myCustomControlTemplate);

我是WPF的新手,所以如果这是一个非常微不足道的问题,请耐心等待。

编辑:(根据Erno的要求)

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文件

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文件

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; }
}

因此,您可以看到我在xaml.cs文件中创建的MyUserControl类型的所有对象将共享公共属性并自行更新。用户将与这些控件进行交互,当他们请求进行某些处理时,我必须查看用户添加到主控件的每个MyUserControl,调用MyUserControl中的一些方法来获取一些信息,使用每个MyUserControl中的这些信息进行其他处理和查询数据库。

我希望这有帮助..

1 个答案:

答案 0 :(得分:1)

修改

请注意,您发布的代码中的ViewModel属性是集合!您可能希望将这些List更改为ObservableCollection。

要绑定到这些:使用诸如ListBox IN USERCONTROL中的itemscontrol。 (顺便说一下:请使用更好的属性名称!)

以下是它的样子:

<StackPanel>
    <MyUserControl DataContext="{Binding Property1}"/>
    <MyUserControl DataContext="{Binding Property2}"/>
    <MyUserControl DataContext="{Binding Property3}"/>
</StackPanel>

在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>

旧答案 - 仍然有效 回应你的意见:

您需要一种非常相似的不同方法。通过使用ListCon之类的ItemsControl,您只需要指定要绑定到的集合,并自动为集合中的每个项目创建ItemTemplate的实例(在本例中包含usercontrol),并设置其DataContext到项目,因此用户控件中的绑定将相对于项目。

无需在代码中添加实例,也无需设置每个控件的DataContext。 欢迎来到精彩的数据绑定世界。

我的猜测是你不是在寻找一个模板而是一个风格:

<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>

在代码中:

myUserControl myUserControl = new MyUserControl;
Style style = MyStackPanel.FindResource("ucStyle") as Style;
if(style != null)
{
    myUserControl.Style = style;
}
myStackPanel.Children.Add(myUserControl);

或者,使用隐式样式更短但不太明显:

<StackPanel x:Name="MyStackPanel">
    <StackPanel.Resources>
        <Style TargetType="MyUserControl">
            <Setter Property="Background" Value="Azure" />
            <Setter Property="BorderThickness" Value="2" />
        </Style>
    </StackPanel.Resources>
</StackPanel>

在代码中:

myUserControl myUserControl = new MyUserControl;
myStackPanel.Children.Add(myUserControl);