0

我目前在我的 wpf 应用程序中使用带有 PRISM 的 MVVM 模式,并且将 Shell、Views 和 ViewModels 全部注入并绑定在一起。(据我所知......这是我的第一个 wpf 应用程序)。我的模块定义正确连接了所有内容。

我必须在我的一个视图上显示大小不一致的对象集合,而不是在后端手动创建它,我想创建一个新的用户控件并将其绑定到单个数据实体,以便我可以保留它是自我认知和管理的,但这些控件需要添加到我认为的网格或面板中。按照前面的例子,我决定沿着界面+具体路径走,以保持更小的部分灵活。

首先,我是否走在正确的道路上?在 ASP.Net 中,我会为显示创建一个模板,然后附加模型。

其次,在我构建主视图时,是否有一种可接受的方式让我的容器解析这个“模板”用户控件?

最初我的代码看起来是这样的,所以我想用另一个 xaml 完全替换它:

            foreach (var node in nodes) {
                var p = new StackPanel();
                p.DataContext = node;
                p.Children.Add(new Label() { Content = node.Name });
                p.Children.Add(new TextBox() { Text = "" });
                NodesControl.Children.Add(p);
            }
4

1 回答 1

2

让 DataTemplates 为您完成工作。

给定一个简单的窗口,具有以下 ViewModel:

public sealed class ViewModel : INotifyPropertyChanged
{
    private object _derper;

    public event PropertyChangedEventHandler PropertyChanged = (o, e) => { };

    public object Derper
    {
        get { return this._derper; }
        set
        {
            this._derper = value;
            PropertyChanged(this, new PropertyChangedEventArgs("Derper"));
        }
    }

    public ICommand OnDerp { get; set; }

    public ViewModel()
    {
        OnDerp = new DerpCommand(this);
    }
}

我们希望为属性 Derper 的不同值显示不同的 UI。该属性由 DerpCommand 设置:

public sealed class DerpCommand : ICommand
{
    public event EventHandler CanExecuteChanged;
    private readonly ViewModel _viewModel;
    private int _count = 0;
    public bool CanExecute(object parameter)
    {
        return true;
    }
    public void Execute(object parameter)
    {
        _viewModel.Derper = _count % 2 == 0 ?
            (object)new Derp() 
                { Herp = "Derped " + (++_count / 2 + 1) + " times." } :
            new Herp() 
                { Derp = "Herped " + (_count++ / 2 + 1) + " times." };
    }
    public DerpCommand(ViewModel viewModel)
    {

        this._viewModel = viewModel;
    }
}

它只是根据运行次数ViewModel.Derper在实例Herp和类型之间切换值。Derp我将省略这些模型的实现,因为它们是具有单个属性的 POCO。无聊的东西。

现在,当ViewModel.Derper属性类型为 时Derp,我们想要一个漂亮的矢车菊蓝色背景,黑色文本前景显示模型的值。当它是 typeHerp时,我们需要黑色背景和白色文本。所以我们DataTemplates为每个创建:

<DataTemplate
    DataType="{x:Type t:Derp}">
    <TextBlock
        Padding="50"
        Background="CornflowerBlue"
        Text="{Binding Herp}" />
</DataTemplate>
<DataTemplate
    DataType="{x:Type t:Herp}">
    <TextBlock
        Padding="50"
        Foreground="White"
        Background="Black"
        Text="{Binding Derp}" />
</DataTemplate>

请注意,在每个DataTemplateDataContext都是指定模型的实例DataType

我们如何连接这些?我们没有。我们只需在 UI 中DataTemplate通过添加 a并将其属性ContentControl绑定到. 这是整个用户界面:ContentViewModel.Derper

<Window
    x:Class="DataTemplateExample.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:t="clr-namespace:DataTemplateExample"
    Title="DataTemplate example"
    Height="350"
    Width="525">
    <Window.DataContext>
        <t:ViewModel />
    </Window.DataContext>
    <Window.Resources>
        <DataTemplate
            DataType="{x:Type t:Derp}">
            <TextBlock
                Padding="50"
                Background="CornflowerBlue"
                Text="{Binding Herp}" />
        </DataTemplate>
        <DataTemplate
            DataType="{x:Type t:Herp}">
            <TextBlock
                Padding="50"
                Foreground="White"
                Background="Black"
                Text="{Binding Derp}" />
        </DataTemplate>
    </Window.Resources>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition
                Height="auto" />
        </Grid.RowDefinitions>
        <ContentControl
            HorizontalAlignment="Center"
            VerticalAlignment="Center"
            Content="{Binding Derper}" />
        <Button
            Grid.Row="1"
            Command="{Binding OnDerp}">Click me to derp</Button>
    </Grid>
</Window>

它是什么样子的:

在此处输入图像描述

毕竟,如果您仍然想使用 Unity 来连接 UI,您可以创建自己的DataTemplateSelector使用 Unity 查找模板。浪费时间恕我直言。顺其自然。

于 2013-09-13T18:07:11.773 回答