1

I am trying to create a re-useable popup user control. It needs to be a usercontrol because it needs to contain a button and a hyperlink which will need code behind when clicked. I want to set the PlacementTarget of the popup to a control (e.g. button) in the parent window, and would like to be able to pass in the control name so that the popup will open next to the relevant control. I have tried the following, but it is not working.

User Control:

<UserControl
  x:Class="SampleTestProject.WPF.VrtContactUserTooltip"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  x:Name="parent">
  <Grid>
    <Popup
    Name="ContactTooltip"
    PlacementTarget="{Binding Path=Target, ElementName=parent}"
    DataContext="{Binding Path=Contact}"/>
    </Grid>
</UserControl>

Code behind for user control:

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

#region Properties

#region Target

/// <summary>
/// Gets or sets the Target of the tooltip
/// </summary>
public string Target
{
  get { return (string)GetValue(TargetProperty); }
  set { SetValue(TargetProperty, value); }
}

/// <summary>
/// Identified the Target dependency property
/// </summary>
public static readonly DependencyProperty TargetProperty =
  DependencyProperty.Register("Target", typeof(string),
    typeof(VrtContactUserTooltip), new PropertyMetadata(""));

#endregion

#region Contact

/// <summary>
/// Gets or sets the Contact of the tooltip
/// </summary>
public Contact Contact
{
  get { return (Contact)GetValue(ContactProperty); }
  set { SetValue(ContactProperty, value); }
}

/// <summary>
/// Identified the Contact dependency property
/// </summary>
public static readonly DependencyProperty ContactProperty =
  DependencyProperty.Register("Contact", typeof(Contact),
    typeof(VrtContactUserTooltip), new PropertyMetadata(null));

#endregion
#endregion
  }
}

Where user control is being used:

 <Button
    x:Name="PopupButton3" />
  <wpf:VrtContactUserTooltip
    Target="{Binding Source={x:Reference PopupButton3}}"
    Contact="{Binding Path=Contact}"/>

Is it possible to do this (i.e. pass a control name from the parent control into the user control and bind to it)?

Eva423
  • 31
  • 10

2 Answers2

0

See: https://stackoverflow.com/a/1127964/1462330

I think you could also rather than doing a find ancestor just pass in explicitly the parent control/window as the data context for the child control and bind to it.

Design wise: it depends on how likely you are to reuse the control. Is the child user control something that is going to be reused and reused in a common scenario? If so, it might be possible to do in XAML but the way I'd handle it would be to define an interface that the control expects its parent to implement, and a constructor that takes something implementing that interface as a parameter. In the C# side I'd cast the parent property to a "IHaveWhatINeed" where I need to make use of the parent controls properties. That'd make both the coupling between the parent and child controls explicit and isolate the coupling to the specific subset of properties/functions that the child relies on from the parent.

private IWhatINeed data;
public ChildControl( IWhatINeed requiredData )
{ ... }
Mike
  • 418
  • 3
  • 10
  • Thanks, Mike. I don't think that using a relative source will work for me because I am trying to bind to a UI control (in this case, a button) rather than something in the VM. However, I'll try initializing it from the code behind. – Eva423 Aug 26 '18 at 16:21
0

I ended up setting the PlacementTarget in the constructor of the window that the user control was being used in. I put the following line in the constructor of the parent window:

ContactPopup3.ContactTooltip.PlacementTarget = PopupButton3;

This is not ideal (as it will need to be set in the code behind every time the user control is used), but it solved the problem.

Eva423
  • 31
  • 10