Шаблон пользовательского контроля wpf - PullRequest
0 голосов
/ 09 мая 2011

В моем приложении 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>

Это правильно выбирает TrialSiteViewModel, который является DataContext для Treeviewitem.

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. Если я изменю код для использования кнопки Command в TrialSiteViewModel и вставлю его в ObjectPreview, я могу установить contentcontrol в приведенном ниже коде и использовать TrialSiteView.

Я предполагаю, что шаблон каким-то образом выведен из TreeViewItem. Может кто-нибудь сказать мне, как я могу убедиться, что подсказка использует TrialSiteView?

UPDATE

Хорошо, я исправил это, но мне пришлось прибегнуть к коду позади, удалить пользовательский контроль и поместить представление прямо во всплывающую подсказку. Ключевым битом является получение таблицы данных из ресурсов. Я пытался сделать это ранее, назначив ключ к табличке данных, но либо мой код был ошибочным, либо он не работал. В любом случае это работает, но не является предпочтительным решением 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;
}

1 Ответ

0 голосов
/ 10 мая 2011

Что вам нужно сделать, это явно указать, какой шаблон данных использовать. Для этого просто добавьте свойство шаблона вместе со свойством 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 добавьте свойство ContentTemplate, связанное со свойством PreviewObjectTemplate:

<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>

...