WPF:如何动态加载用户控件?

时间:2022-09-10 15:51:51

How can I load WPF based user control in WPF based window dynamically (using code at runtime)?

如何动态地在基于WPF的窗口中加载基于WPF的用户控件(在运行时使用代码)?

3 个解决方案

#1


21  

I'd highly recommend having a look at Prism, since composite user interfaces is what it's for. However, since this would require you refactoring your entire application, I'll also answer your question directly.

我强烈建议您查看Prism,因为复合用户界面就是它的用途。但是,由于这需要您重构整个应用程序,我还会直接回答您的问题。

If you want a single user control in a container, put a ContentControl in your XAML and then set the Content property. If you are using a view model, you could bind Content to a FrameworkElement property on the view model:

如果要在容器中使用单个用户控件,请将ContentControl放入XAML中,然后设置Content属性。如果您使用的是视图模型,则可以将Content绑定到视图模型上的FrameworkElement属性:

contentControlInstance.Content = new CustomUserControl();

If you want multiple controls in a list, use an ItemsControl and assign an ObservableCollection<> to the ItemsSource property. If you are using a view model, you could bind ItemsSource to an ObservableCollection property on the View Model.

如果要在列表中使用多个控件,请使用ItemsControl并将一个ObservableCollection <>分配给ItemsSource属性。如果您使用的是视图模型,则可以将ItemsSource绑定到View Model上的ObservableCollection属性。

Then you can just add/remove views from that ObservableCollection:

然后你可以添加/删除ObservableCollection中的视图:

private ObservableCollection<FrameworkElement> views = 
    new ObservableCollection<FrameworkElement>();

private void Initialize()
{
    itemsControl.ItemsSource = views;
}

private void AddView(FrameworkElement frameworkElement)
{
    views.Add(frameworkElement);
}

#2


4  

For adding multiple controls you need container.

要添加多个控件,您需要容器。

Suppose you have a StackPanel container "myStack"

假设你有一个StackPanel容器“myStack”

<Window ..>
    <StackPanel Name="MyStack" />
</Window>

You can create control dynamically and add it to container. See code below

您可以动态创建控件并将其添加到容器中。见下面的代码

void AddButtons()
{
    Button B1=new Button(),B2=new Button(), B3=new Button();
    B1.Content="Hello";
    B2.Content="First";       
    B3.content="Application";
   // Now you can set more properties like height, width, margin etc...
    MyStack.Children.Add(B1);
    MyStack.Children.Add(B2);
    MyStack.Children.Add(B2);    
}

#3


3  

Or use binding. Here's a really crude example showing how different WPF controls can be shown in a single WPF window using ContentControl and binding (which is what a toolkit like Prism or Caliburn Micro does).

或者使用绑定。这是一个非常粗略的例子,展示了如何使用ContentControl和绑定(这是像Prism或Caliburn Micro这样的工具包)在单个WPF窗口中显示不同的WPF控件。

XAML:

XAML:

<UserControl x:Class="ViewA">
  ...
<UserControl/>

<UserControl x:Class="ViewB">
  ...
<UserControl/>

Code:

码:

void ShowViewModelDialog (object viewModel)
{
  var host = new MyViewHost();
  FrameworkElement control = null;
  string viewModelName = viewModel.GetType().Name;
  switch (viewModelName )
  {
     case ("ViewModelA"):
       control  = new ViewA();
       break;
     case ("ViewModelB"):
       control  = new ViewB();
       break;
     default:
       control = new TextBlock {Text = String.Format ("No view for {0}", viewModelName);
       break;
  }

  if (control!=null) control.DataContext = viewModel;
  host.DataContext = control;
  host.Show(); // Host window will show either ViewA, ViewB, or TextBlock.
}

#1


21  

I'd highly recommend having a look at Prism, since composite user interfaces is what it's for. However, since this would require you refactoring your entire application, I'll also answer your question directly.

我强烈建议您查看Prism,因为复合用户界面就是它的用途。但是,由于这需要您重构整个应用程序,我还会直接回答您的问题。

If you want a single user control in a container, put a ContentControl in your XAML and then set the Content property. If you are using a view model, you could bind Content to a FrameworkElement property on the view model:

如果要在容器中使用单个用户控件,请将ContentControl放入XAML中,然后设置Content属性。如果您使用的是视图模型,则可以将Content绑定到视图模型上的FrameworkElement属性:

contentControlInstance.Content = new CustomUserControl();

If you want multiple controls in a list, use an ItemsControl and assign an ObservableCollection<> to the ItemsSource property. If you are using a view model, you could bind ItemsSource to an ObservableCollection property on the View Model.

如果要在列表中使用多个控件,请使用ItemsControl并将一个ObservableCollection <>分配给ItemsSource属性。如果您使用的是视图模型,则可以将ItemsSource绑定到View Model上的ObservableCollection属性。

Then you can just add/remove views from that ObservableCollection:

然后你可以添加/删除ObservableCollection中的视图:

private ObservableCollection<FrameworkElement> views = 
    new ObservableCollection<FrameworkElement>();

private void Initialize()
{
    itemsControl.ItemsSource = views;
}

private void AddView(FrameworkElement frameworkElement)
{
    views.Add(frameworkElement);
}

#2


4  

For adding multiple controls you need container.

要添加多个控件,您需要容器。

Suppose you have a StackPanel container "myStack"

假设你有一个StackPanel容器“myStack”

<Window ..>
    <StackPanel Name="MyStack" />
</Window>

You can create control dynamically and add it to container. See code below

您可以动态创建控件并将其添加到容器中。见下面的代码

void AddButtons()
{
    Button B1=new Button(),B2=new Button(), B3=new Button();
    B1.Content="Hello";
    B2.Content="First";       
    B3.content="Application";
   // Now you can set more properties like height, width, margin etc...
    MyStack.Children.Add(B1);
    MyStack.Children.Add(B2);
    MyStack.Children.Add(B2);    
}

#3


3  

Or use binding. Here's a really crude example showing how different WPF controls can be shown in a single WPF window using ContentControl and binding (which is what a toolkit like Prism or Caliburn Micro does).

或者使用绑定。这是一个非常粗略的例子,展示了如何使用ContentControl和绑定(这是像Prism或Caliburn Micro这样的工具包)在单个WPF窗口中显示不同的WPF控件。

XAML:

XAML:

<UserControl x:Class="ViewA">
  ...
<UserControl/>

<UserControl x:Class="ViewB">
  ...
<UserControl/>

Code:

码:

void ShowViewModelDialog (object viewModel)
{
  var host = new MyViewHost();
  FrameworkElement control = null;
  string viewModelName = viewModel.GetType().Name;
  switch (viewModelName )
  {
     case ("ViewModelA"):
       control  = new ViewA();
       break;
     case ("ViewModelB"):
       control  = new ViewB();
       break;
     default:
       control = new TextBlock {Text = String.Format ("No view for {0}", viewModelName);
       break;
  }

  if (control!=null) control.DataContext = viewModel;
  host.DataContext = control;
  host.Show(); // Host window will show either ViewA, ViewB, or TextBlock.
}