开发者

wpf Usercontrol template

开发者 https://www.devze.com 2023-03-04 18:30 出处:网络
In my MVVM app I have a treeview representing records in a database. My views and viewmodels are linked in a resource dictionary like this

In my MVVM app I have a treeview representing records in a database. My views and viewmodels are linked in a resource dictionary like this

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

I want to display a preview of the view when a user hovers over an icon using the tooltip. My HierarchicalDataTemplate in the treeview is this

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

This correctly picks up the TrialSiteViewModel that is the DataContext for the Treeviewitem.

ObjectPreview uses a viewbox and contentcontrol to display the view of the record

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

and the code behind contains the dependency property

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); }
  }
 }

The problem I'm having is that the Template use开发者_开发百科d to display the object is the same as that used in the treeview. This simply shows an icon and an object summary (ie. Primary Key and one or two key fields) rather than the entire template as defined in the view TrialSiteView. If I amend the code to use a button Command on the TrialSiteViewModel and inject it into ObjectPreview I can set the contentcontrol in the code behind and the TrialSiteView is used.

I'm guessing that somehow the Template is inferred from the TreeViewItem. Can anyone tell me how I can ensure the tooltip uses the TrialSiteView?

UPDATE

Ok, so I've fixed this but had to resort to code behind and removed the usercontrol and put the view directly in the tooltip. The key bit is getting the datatemplate from the resources. I'd tried to do this previously by assigning a key to the datatemplate, but either my code was flawed or it did not work. Anyhow, this works but is not the preferred Xaml solution.

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


What you need to do is to specify explicitly what data template to use. In order to do that just add a template property along with the PreviewObject property in the preview control:

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

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

Then, in the ObjectPreview.xaml add the ContentTemplate property that is bound to the PreviewObjectTemplate property:

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

And finally, give a key to your data template and specify a reference to it explicitly when you declare 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>

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号