使用 WPF/MVVM 在运行时动态更改 UserControl 内容

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

Dynamically changing UserControl content at run time with WPF/MVVM

c#wpfuser-controls

提问by NZJames

The screen I am trying to create is a multi-part results viewer. When your batch job completes, you will be able to double click on it and open this screen, which will contain a top section of basic data about the batch job that just ran (top 30% of screen, full width), then the lower 70% will consist of a left aligned listbox (20% of the width) with a selection of Sub-Results and a Detail pane taking up the remaining 80% of the width.

我试图创建的屏幕是一个多部分结果查看器。批处理作业完成后,您将能够双击它并打开此屏幕,其中包含有关刚刚运行的批处理作业的基本数据的顶部部分(屏幕顶部 30%,全宽),然后是底部70% 将包含一个左对齐的列表框(宽度的 20%),其中包含一个子结果选择和一个占据剩余 80% 宽度的详细信息窗格。

The way I want it to behave is when you select the Sub Result on the left listbox, the right hand pane will populate with the details of the sub result. Because it is going to be complex and needs to be scalable, I would like to implement each sub result detail display panel as a UserControl.

我希望它的行为方式是当您选择左侧列表框中的子结果时,右侧窗格将填充子结果的详细信息。因为它会很复杂并且需要可扩展,所以我想将每个子结果详细信息显示面板实现为一个 UserControl。

The parent ViewModel contains an IDictionary<Enum.ResultType, IResultPanel>- and the listbox will be populated from the keys of this dictionary, and when you select an option, it will fetch the IResultPanel object from the dictionary which will be User Control, one example snippet below

父 ViewModel 包含一个IDictionary<Enum.ResultType, IResultPanel>- 并且列表框将从此字典的键填充,当您选择一个选项时,它将从字典中获取 IResultPanel 对象,该对象将是用户控件,下面是一个示例片段

public partial class SimpleCalcInfoResult : UserControl, IResultPanel
    {
        private SimpleCalcInfoResultViewModel _viewModel;

        public SimpleCalcInfoResult(SimpleCalcInfoResultViewModel viewModel)
        {
            InitializeComponent();
            _viewModel = viewModel;
        }
    }

The IResultPanel interface is a blank empty interface, used only to facilitate being able to have the Dictionary above with a common type as I felt having a dictionary of UserControls was too broad.

IResultPanel 接口是一个空白的空接口,只是为了方便上面的 Dictionary 有一个通用类型,因为我觉得有一个 UserControls 的字典太宽泛了。

The problem I've got is I can't figure out what XAML to use in the parent control to have a changeable UserControl panel. Obviously you can have

我遇到的问题是我无法弄清楚在父控件中使用什么 XAML 来拥有一个可更改的 UserControl 面板。显然你可以有

<local:MyControl> ... </local:MyControl>

As a hard coded user control, but how can I have a section of XAML that will let me change which User Control is displayed, depending on which ListBox item you select?

作为硬编码的用户控件,但我如何才能拥有一部分 XAML 来让我更改显示的用户控件,具体取决于您选择的 ListBox 项目?

回答by Sheridan

This is simple to achieve with WPF. However, when using MVVM, we 'manipulate' data rather than UI controls. With that in mind, first declare a DataTemplatefor each of your custom Panelcontrols in the Application.Resourcessection:

这很容易用 WPF 实现。但是,在使用 MVVM 时,我们“操纵”数据而不是 UI 控件。考虑到这一点,首先声明一个DataTemplate为每个自定义的Panel在控制Application.Resources部分:

<DataTemplate DataType="{x:Type ViewModels:SimpleCalcInfoResultViewModel}">
    <Views:SimpleCalcInfoResult />
</DataTemplate>
...
<DataTemplate DataType="{x:Type ViewModels:MainViewModel}">
    <Views:MainView />
</DataTemplate>

Now all you have to do is display the relating view model in your lower right display using a ContentControl:

现在您所要做的就是使用以下命令在右下方显示中显示相关的视图模型ContentControl

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

Finally, add a property of type IResultPanelnamed ViewModelto your parent view model:

最后,将一个IResultPanel名为name 的属性添加ViewModel到您的父视图模型中:

private IResultPanel viewModel = new FirstViewModel();

public IResultPanel ViewModel
{
    get { return viewModel; }
    set { if (viewModel != value) { viewModel = value; NotifyPropertyChanged("ViewModel"); } }
}

Now all you need to do to display a different Panelin your application is to set this property to a different value:

现在你需要做的就是Panel在你的应用程序中显示一个不同的值,就是将此属性设置为不同的值:

ViewModel = new SimpleCalcInfoResultViewModel();