如何以编程方式将DataTemplate应用于View Model类

时间:2013-09-18 15:04:56

标签: c# wpf xaml datatemplate

在我的WPF应用程序中,我有MainWindow控件,而GraphControl用户控件放在Window中的XAML标记。 GraphControl已分配GraphControlViewModel,其中包含附件GraphView控件(源自Control类)。这些类型的实现的概要(简化)如下:

GraphControl.xaml

<UserControl
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:designer="clr-namespace:Designer"
  xmlns:GraphUI="clr-namespace:GraphUI;assembly=GraphUI"
  xmlns:GraphModel="clr-namespace:GraphModel;assembly=GraphModel">

  /* simplified document content */

  <UserControl.Resources>

    <ResourceDictionary>

      <DataTemplate DataType="{x:Type GraphModel:NodeViewModel}">

          /* data template definition here*/

      </DataTemplate>

    </ResourceDictionary>

  </UserControl.Resources>

  <UserControl.DataContext>
    <designer:GraphControlViewModel />
  </UserControl.DataContext>

  <DockPanel>

    <GraphUI:GraphView NodesSource="{Binding Graph.Nodes}" />

  </DockPanel>

</UserControl>

GraphControlViewModel.cs:

public class GraphControlViewModel : AbstractModelBase
{
    private GraphViewModel graph;

    public GraphViewModel Graph
    {
        get
        {
            return this.graph;
        }
        set
        {
            this.graph = value;

            this.OnPropertyChanged("Graph");
        }
    }

    // implementation here
}

GraphViewModel.cs:

public sealed class GraphViewModel
{
    private ImpObservableCollection<NodeViewModel> nodes;

    public ImpObservableCollection<NodeViewModel> Nodes
    {
        get
        {
            return this.nodes ?? ( this.nodes = new ImpObservableCollection<NodeViewModel>() );
        }
    }

    // implementation here
}

NodeViewModel.cs:

public sealed class NodeViewModel : AbstractModelBase
{
   // implementation here
}

GraphView.cs:

public partial class GraphView : Control
{
    // implementation of display details here

    public IEnumerable NodesSource
    {
        get
        {
            return (IEnumerable)this.GetValue(NodesSourceProperty);
        }
        set
        {
            this.SetValue(NodesSourceProperty, value);
        }
    }
}

应用程序的工作和外观一如既往,DataTemplate已正确应用于View Model类。

但是,目前,为了便于访问,需要将x:key属性添加到DataTemplate定义:

<DataTemplate x:Key="NodeViewModelKey" DataType="{x:Type GraphModel:NodeViewModel}">

    /* data template definition here*/

</DataTemplate>

我的问题出现了。正如在MSDN上的Data Templating Overview文档中所述:

If you assign this DataTemplate an x:Key value, you are overriding the implicit x:Key and the DataTemplate would not be applied automatically.

确实,在我添加x:Key属性后,DataTemplate未应用于我的View Model类。

如何在我的情况下以编程方式应用DataTemplate?

2 个答案:

答案 0 :(得分:1)

我会尝试向DataTemplate添加GraphView依赖项属性,然后尝试使用类似这样的内容:

<GraphUI:GraphView NodesSource="{Binding Graph.Nodes}" 
                   DataTemplate={StaticResource NodeViewModelKey}/>

答案 1 :(得分:1)

如果您将GraphView命名为:

<GraphUI:GraphView x:Name="myGraph" NodesSource="{Binding Graph.Nodes}" />

在你的usercontrol后面的代码中你可以这样做:

      myGraph.Resources.Add(
      new DataTemplateKey(typeof(NodeViewModel)), 
      Resources["NodeViewModelKey"]);