1

我有一个用户控件,我想在 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 的这些信息进行一些其他处理和查询数据库。

我希望这有帮助..

4

1 回答 1

1

编辑

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

要绑定到这些:使用项目控件,例如用户控件中的列表框。(顺便说一句:请使用更好的属性名称!)

这是它的样子:

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

旧答案 - 仍然有效 针对您的评论:

您需要一种非常相似的不同方法。通过使用诸如 ListBox 之类的 ItemsControl,您只需指定要绑定到的集合,并自动为集合中的每个项目创建 ItemTemplate 的实例(在本例中包含用户控件)并设置其 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);
于 2012-08-30T05:13:04.020 回答