wpf 将 ContentControl 绑定到 UserControl,并重用相同的实例

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15679918/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 08:21:42  来源:igfitidea点击:

Binding a ContentControl to UserControl, and reuse same instance

c#wpfxamlbindingcontentcontrol

提问by cederlof

I'm trying to bind a ContentControl's Content to a UserControl I have instantiated in my ViewModel. I cannot use the method with binding to a ViewModel and then have the UserControl be the DataTemplate of the ViewModel, as I need the Content of the ContentControl to be able to change frequently, using the same instanceof the UserControls/Views, and not instantiate the views each time i re-bind.

我正在尝试将 ContentControl 的内容绑定到我在 ViewModel 中实例化的 UserControl。我不能使用绑定到 ViewModel 的方法,然后让 UserControl 成为 ViewModel 的 DataTemplate,因为我需要 ContentControl 的内容能够经常更改,使用UserControls/Views的相同实例,而不是实例化每次重新绑定时的视图。

However, when setting the UserControl-property to a UserControl-instance, and then when the view is rendered/data-bound I get: Must disconnect specified child from current parent Visual before attaching to new parent Visual.Even though I have not previously added this UserControl to anywhere, I just created this instance earlier and kept it in memory.

但是,当将 UserControl-property 设置为 UserControl-instance 时,然后当视图呈现/绑定数据时,我得到:在附加到新的父 Visual 之前,必须断开指定的子级与当前父 Visual 的连接。尽管我之前没有将这个 UserControl 添加到任何地方,但我只是更早地创建了这个实例并将它保存在内存中。

Are there a better way to achieve what I am doing?

有没有更好的方法来实现我正在做的事情?

In the ViewModel

在视图模型中

public class MyViewModel : INotifyPropertyChanged
{
    //...

    private void LoadApps()
    {
        var instances = new List<UserControl>
                          {
                              new Instance1View(),
                              new Instance2View(),
                              new Instance3View(),
                          };
        SwitchInstances(instances);
    }

    private void SwitchInstances(List<UserControl> instances)
    {
        CenterApp = instances[0];
    }

    //...

    private UserControl _centerApp;
    public UserControl CenterApp
    {
        get { return _centerApp; }

        set
        {
            if (_centerApp == value)
            {
                return;
            }

            _centerApp = value;
            OnPropertyChanged("CenterApp");
        }
    }

    //...
}

In the View.xaml

在 View.xaml

<ContentControl Content="{Binding CenterApp}"></ContentControl>

回答by Viv

Too long for a comment.

评论太长了。

Building up on what @Kent stated in your comment, The whole point of MVVM is to disconnect the view-model from view related stuff(controls) which blocks the testing capability of GUI applications. Thus you having a UserControl / Button / whatever graphical view-related item negates the entire principle of MVVM.

建立在@Kent 在您的评论中所说的内容的基础上,MVVM 的重点是将视图模型与视图相关的东西(控件)断开,这会阻止 GUI 应用程序的测试能力。因此,您拥有一个 UserControl / Button / 任何与图形视图相关的项目都会否定 MVVM 的整个原则。

You should if using MVVM comply with its standards and then re-address your problem.

如果使用 MVVM,您应该遵守其标准,然后重新解决您的问题。

  1. With MVVM you normally have 1 view <-> 1 view-model
  2. View knows about its View Model(Normally through DataContext). Reverse should not be coded into.
  3. You try to put logic controlling the view in the view-model to allow testing logic(Commands and INPC properties)
  1. 使用 MVVM,您通常有 1 个视图 <-> 1 个视图模型
  2. View 知道它的 View Model(通常通过 DataContext)。不应将反向编码为。
  3. 您尝试将控制视图的逻辑放在视图模型中以允许测试逻辑(命令和 INPC 属性)

... and quite a few more. It's pretty specific in the extents of view-model not having view related stuff for eg not even having properties in view-model like Visibility. You normally hold a booland then in the view use a converter to switch it to the Visibilityobject.

……还有很多。它在视图模型的范围内非常具体,没有与视图相关的东西,例如在视图模型中甚至没有像Visibility. 您通常按住 abool然后在视图中使用转换器将其切换到Visibility对象。

Reading up a bit more into MVVM would certainly help you,

多读一点 MVVM 肯定会对你有帮助,

Now for something to address your current issue:

现在要解决您当前的问题:

Following a MVVM structure,

遵循 MVVM 结构,

your going to have ViewModels such as

您将拥有 ViewModels,例如

  • Main: MyViewModel
  • Derive all instance ViewModels from a base to allow them being kept in a list.
  • List or hold individually Instance1ViewModel, Instance2ViewModel, Instance3ViewModelin MyViewModel(Either create it yourself or if your using an IOC container let it inject it)
  • Have MyViewModelexpose a property just like your posted example:
  • 主要的: MyViewModel
  • 从基础派生所有实例 ViewModel 以允许将它们保存在列表中。
  • 单独列出或保持Instance1ViewModel, Instance2ViewModel, Instance3ViewModelin MyViewModel(要么自己创建,要么使用 IOC 容器让它注入它)
  • MyViewModel暴露的属性,就像您发布的例子:

Example:

例子:

// ViewModelBase is the base class for all instance View Models
private ViewModelBase _currentFrame;
public ViewModelBase CurrentFrame {
  get {
    return _currentFrame;
  }

  private set {
    if (value == _currentFrame)
      return;
    _currentFrame = value;
    OnPropertyChanged(() => CurrentFrame);
  }
}
  • Now in your MyView.xamlView file you should(does'nt have to be top level) set the top-level DataContext to your MyViewModel
  • Your View's xaml can then be declared like:
  • 现在在您的MyView.xaml视图文件中,您应该(不必是顶级)将顶级 DataContext 设置为您的MyViewModel
  • 然后可以像这样声明您的视图的 xaml:

Example:

例子:

...
<Window.Resources>
  <DataTemplate DataType="{x:Type local:Instance1ViewModel}">
    <local:Instance1View />
  </DataTemplate>
  <DataTemplate DataType="{x:Type local:Instance2ViewModel}">
    <local:Instance2View />
  </DataTemplate>
  <DataTemplate DataType="{x:Type local:Instance3ViewModel}">
    <local:Instance3View />
  </DataTemplate>
</Window.Resources>
<Grid>
  <ContentControl Content="{Binding Path=CurrentFrame}" />
</Grid>
...
  • Thats it!. Now you just switch the CurrentFrameproperty in your view-model and make it point to any of three instance view-models and the view will be correspondingly updated.
  • 就是这样!。现在您只需切换CurrentFrame视图模型中的属性并使其指向三个实例视图模型中的任何一个,视图就会相应地更新。

This gets you an MVVM compliant application, for your other issue of working around not having to recreate views dynamically based on DataTemplate you could follow the approaches suggested hereand expand it for your own usage.

这为您提供了一个 MVVM 兼容的应用程序,对于您不必根据 DataTemplate 动态重新创建视图的其他问题,您可以按照此处建议的方法进行扩展以供您自己使用。