将ContentControl绑定到UserControl,然后重用同一实例 [英] Binding a ContentControl to UserControl, and reuse same instance

查看:446
本文介绍了将ContentControl绑定到UserControl,然后重用同一实例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将ContentControl的内容绑定到我在ViewModel中实例化的UserControl。我无法使用绑定到ViewModel的方法,然后将UserControl用作ViewModel的DataTemplate,因为我需要使用相同的实例来频繁更改ContentControl的内容

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 instance of the UserControls/Views, and not instantiate the views each time i re-bind.

但是,在将UserControl属性设置为UserControl实例时,然后在视图时,不会实例化视图渲染/数据绑定我得到:在附加到新的父Visual之前,必须将指定的孩子与当前的父Visual断开连接。即使我以前没有将此UserControl添加到任何地方,我还是早先创建了此实例,并且将其保存在内存中。

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.

是否有更好的方法来实现我的工作?

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

在ViewModel中

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

    //...
}

在View.xaml中

In the View.xaml

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


推荐答案

评论太久了。

以@Kent在您的评论中所述的内容为基础,MVVM的全部目的是将视图模型与视图相关的东西(控件)断开连接,这会阻塞GUI应用程序的测试能力。因此,拥有UserControl / Button /与图形视图相关的任何项都否定了MVVM的整个原理。

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.

如果使用MVVM,则应遵守其标准,然后重新寻址您的问题。

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


  1. 使用MVVM,您通常有1个视图<-> 1个视图模型

  2. View了解其视图模型(通常通过DataContext)。

  3. 您尝试将控制视图的逻辑放在视图模型中以允许测试逻辑(命令和INPC属性)

...等等。它在视图模型的范围内非常具体,因为它没有与视图相关的内容,例如,甚至没有视图模型中的属性,例如 Visibility 。通常,您拿着一个 bool ,然后在视图中使用转换器将其切换到 Visibility 对象。

... 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 bool and then in the view use a converter to switch it to the Visibility object.

多读一些MVVM肯定会对您有所帮助。

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

现在要解决当前问题:

按照MVVM结构,

您将拥有ViewModel,例如

your going to have ViewModels such as


  • 主要: MyViewModel

  • 从基础派生所有实例ViewModel以便允许它们

  • 列出或单独保存 Instance1ViewModel Instance2ViewModel MyViewModel 中的 Instance3ViewModel (可以自己创建,也可以使用IOC容器注入)

  • 具有 MyViewModel 公开一个属性,就像您发布的示例一样:

  • Main: MyViewModel
  • Derive all instance ViewModels from a base to allow them being kept in a list.
  • List or hold individually Instance1ViewModel, Instance2ViewModel, Instance3ViewModel in MyViewModel (Either create it yourself or if your using an IOC container let it inject it)
  • Have MyViewModel expose a property just like your posted 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);
  }
}




  • 现在您的 MyView.xaml 查看文件,您应该(不必是顶级)将顶级DataContext设置为您的 MyViewModel

  • 然后可以这样声明View的xaml:

    • Now in your MyView.xaml View 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:
    • 示例:

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




      • 就是这样!现在,您只需在视图模型中切换 CurrentFrame 属性,并使其指向三个实例视图模型中的任何一个,视图就会相应地更新。

        • Thats it!. Now you just switch the CurrentFrame property in your view-model and make it point to any of three instance view-models and the view will be correspondingly updated.
        • 这为您提供了一个符合MVVM的应用程序,对于您不必解决基于DataTemplate动态重新创建视图的其他问题,您可以遵循建议的方法此处并将其展开以供您自己使用。

          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 here and expand it for your own usage.

          这篇关于将ContentControl绑定到UserControl,然后重用同一实例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆