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

时间:2013-03-28 10:53:20

标签: c# wpf xaml binding contentcontrol

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

但是,当将UserControl属性设置为UserControl实例时,然后当呈现视图/数据绑定时,我得到:必须在连接到新父Visual之前断开指定子视图与当前父Visual。 / em>即使我以前没有将这个UserControl添加到任何地方,我只是提前创建了这个实例并将其保存在内存中。

有没有更好的方法来实现我的目标?

在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

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

1 个答案:

答案 0 :(得分:2)

评论太长了。

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

如果使用MVVM符合其标准,然后重新解决您的问题,您应该这样做。

  1. 使用MVVM,您通常有1个视图&lt; - &gt; 1视图模型
  2. View了解其视图模型(通常通过DataContext)。反向不应编入。
  3. 您尝试将控制视图的逻辑放在视图模型中以允许测试逻辑(命令和INPC属性)
  4. ......还有更多。它在视图模型的范围内非常具体,没有视图相关的东西,例如甚至没有视图模型中的属性,如Visibility。您通常持有bool,然后在视图中使用转换器将其切换到Visibility对象。

    进一步了解MVVM肯定会对你有所帮助,

    现在可以解决当前问题:

    遵循MVVM结构,

    你将拥有像

    这样的ViewModels
    • 主要:MyViewModel
    • 从基础派生所有实例ViewModel,以允许它们保存在列表中。
    • Instance1ViewModel中单独列出或暂停Instance2ViewModelInstance3ViewModelMyViewModel(自行创建或使用IOC容器让其注入)
    • MyViewModel公开一个属性,就像发布的示例一样:

    示例:

    // 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可以声明为:

    示例:

    ...
    <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属性,并使其指向三个实例视图模型中的任何一个,视图将相应更新。

    这会让你获得一个符合MVVM标准的应用程序,因为你无需基于DataTemplate动态重新创建视图,你可以按照建议的方法here进行扩展,并根据自己的需要进行扩展。