【问题标题】:wpf Usercontrol templatewpf 用户控件模板
【发布时间】:2011-05-09 08:51:50
【问题描述】:

在我的 MVVM 应用程序中,我有一个表示数据库中记录的树视图。我的视图和视图模型在这样的资源字典中链接

<DataTemplate DataType="{x:Type vm:TrialSiteViewModel}">
   <vw:TrialSiteView />
  </DataTemplate>

我想在用户使用工具提示将鼠标悬停在图标上时显示视图的预览。我在树视图中的 HierarchicalDataTemplate 是这样的

   <HierarchicalDataTemplate DataType="{x:Type vm:TrialSiteViewModel}" 
                ItemsSource="{Binding Path=Children}">    
...
     <Button Style="{StaticResource previewButtonStyle}">
      <Button.ToolTip>       
       <ToolTip Style="{x:Null}">
        <ToolTip.ContentTemplate>
         <DataTemplate>          
          <localtools:ObjectPreview 
           PreviewObject="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type TreeViewItem}}, Path=DataContext}"
          />          
         </DataTemplate>
        </ToolTip.ContentTemplate>
       </ToolTip>
      </Button.ToolTip>
     </Button>
    </StackPanel>
   </HierarchicalDataTemplate>

这会正确选取作为 Treeviewitem 的 DataContext 的 TrialSiteViewModel。

ObjectPreview 使用 viewbox 和 contentcontrol 来显示记录的视图

   <Viewbox Grid.Row="1" Name="treeviewViewBox" 
        Stretch="Uniform"
        IsEnabled="False">    
    <ContentControl Name="treeViewItemViewModel"
            Content="{Binding PreviewObject}">
    </ContentControl>
   </Viewbox>

并且后面的代码包含依赖属性

public partial class ObjectPreview : UserControl
 {
  public ObjectPreview()
  {
   InitializeComponent();
  }

  public static readonly DependencyProperty _previewObjectProperty =
    DependencyProperty.Register("PreviewObject", typeof(TreeViewItemViewModel), typeof(ObjectPreview));

  public TreeViewItemViewModel PreviewObject
  {
   get { return (TreeViewItemViewModel)GetValue(_previewObjectProperty); }
   set { SetValue(_previewObjectProperty, value); }
  }
 }

我遇到的问题是用于显示对象的模板与树视图中使用的模板相同。这只是显示了一个图标和一个对象摘要(即主键和一个或两个关键字段),而不是视图 TrialSiteView 中定义的整个模板。如果我修改代码以在 TrialSiteViewModel 上使用按钮命令并将其注入 ObjectPreview,我可以在后面的代码中设置 contentcontrol 并使用 TrialSiteView。

我猜想以某种方式从 TreeViewItem 推断出模板。谁能告诉我如何确保工具提示使用 TrialSiteView?

更新

好的,所以我已经解决了这个问题,但不得不求助于后面的代码并删除了用户控件并将视图直接放在工具提示中。关键是从资源中获取数据模板。我之前曾尝试通过为数据模板分配一个键来执行此操作,但是我的代码有缺陷或无法正常工作。无论如何,这可行,但不是首选的 Xaml 解决方案。

private void PreviewObject_MouseEnter(object sender, MouseEventArgs e)
{
  Image image = (Image)sender;

  var key = new System.Windows.DataTemplateKey(image.DataContext.GetType());
  var datatemplate = (DataTemplate)this.FindResource(key);

  ToolTip tooltip = new ToolTip();
  tooltip.Style = VisualUtils.GetResource<Style>("ControlTemplates.xaml", "toolTipWithContentStyle");
  tooltip.MaxWidth = 460;

  ContentControl contentcontrol = new ContentControl();
  contentcontrol.ContentTemplate = datatemplate;
  contentcontrol.Content = image.DataContext as TreeViewItemViewModel;
  Viewbox viewbox = new Viewbox();
  viewbox.Stretch = Stretch.Uniform;
  viewbox.Child = contentcontrol;

  tooltip.Content = viewbox;
  image.ToolTip = tooltip;
}

【问题讨论】:

  • 您的视图模型只有一个 DataTemplate,因此它将应用于每个内容控件。如果你想使用不同的模板 - 明确应用它。

标签: wpf datatemplate


【解决方案1】:

您需要做的是明确指定要使用的数据模板。为此,只需在预览控件中添加一个模板属性和 PreviewObject 属性:

public static readonly DependencyProperty _previewObjectTemplateProperty =
    DependencyProperty.Register("PreviewObjectTemplate", typeof(DataTemplate), typeof(ObjectPreview));

  public DataTemplate PreviewObjectTemplate
  {
   get { return (DataTemplate)GetValue(_previewObjectTemplateProperty); }
   set { SetValue(_previewObjectTemplateProperty, value); }
  }

然后,在ObjectPreview.xaml 中添加绑定到PreviewObjectTemplate 属性的ContentTemplate 属性:

<Viewbox Grid.Row="1" Name="treeviewViewBox" 
         Stretch="Uniform"
         IsEnabled="False">    
    <ContentControl Name="treeViewItemViewModel"
                    Content="{Binding PreviewObject}"
                    ContentTemplate="{Binding PreviewObjectTemplate}" >
    </ContentControl>
</Viewbox>

最后,在声明ObjectPreview 时,为您的数据模板提供一个键并明确指定对它的引用:

<DataTemplate x:Key="FullViewTemplate" DataType="{x:Type vm:TrialSiteViewModel}">
   <vw:TrialSiteView />
</DataTemplate>

...

<ToolTip Style="{x:Null}">
 <ToolTip.ContentTemplate>
  <DataTemplate>          
   <localtools:ObjectPreview 
    PreviewObject="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type TreeViewItem}}, Path=DataContext}"
    PreviewObjectTemplate="{StaticResource FullViewTemplate}"
   />          
  </DataTemplate>
 </ToolTip.ContentTemplate>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-05-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-30
    • 2015-09-07
    相关资源
    最近更新 更多