Let's say I have control A
that has attached property AP
. And a control B
uses it as A.AP="value"
.
The attached property changed event signature is the same as dependency property, only d
is now the element that is attaching i.e. B
. How do I access A
inside the changed event?
I want to hide A
if AP == null
and more
private static void OnApChanged
(DependencyObject d, DependencyPropertyChangedEventArgs e)
Please note that I am aware that "usually" an attached property use is to set something on the attaching control i.e. A
would normally manipulate B
properties in order to achieve something. But it is just one scenario. I am working on different scenario when B
doesn't know about A
existence - A
is buried somewhere in the visual tree (or might even not be there at all) and what I need is for B
actually set AP
to a string and A
should be able to react on changes and work with the value. It does sound a lot like dependency property (which attached properties are very much alike) but only without B
awareness of A
.
At this moment what I am trying to do is this - I want a user control HelpButton (HB
) which has a button and TopicName property on it. I want to have it in any arbitrary FrameworkElement
children. Parent is not aware of it and HB
is not aware of the parent. When there is TopicName set the HB is visible. If you click on it it opens help window using only TopicName, no other information required.
Let me summarize my understanding of the problem first. You have a HelpButton
control named HB
and it has a TopicName
property. When TopicName
is empty HB
should be hidden, otherwise it should, when clicked, open a window based on TopicName
(I'm assuming HelpButton
is handling all this logic internally). However you want any other element to be able to set HB
's TopicName
without actually needing a reference to an instacne of HB
itself.
It appears what you're looking for isn't well suited to attached properties because attached properties still require an instance for the target object, while there is no instance of the owning type involved. If we make HelpButton
the owning type, this doesn't work because HelpButton
is the one whose property we need to change. If we make something else the owning type, this also doesn't work because no one else has access to an instance of HelpButton
per your problem. So attached properties I think are the wrong track here.
I would keep HelpButton.TopicName
a standard DependencyProperty
owned by HelpButton
(i.e. not an attached property). Then I think a singleton view model that all UI elements can access/bind to serves the function you were trying to implement through an attached property. Here's a rough example:
View Model
public static class ViewModels
{
public static HelpViewModel HelpViewModel
{
get;
} = new HelpViewModel();
}
public class HelpViewModel : ViewModel
{
#region string HelpTopic property
private string _HelpTopic;
public string HelpTopic
{
get
{
return _HelpTopic;
}
set
{
if (_HelpTopic == value)
return;
_HelpTopic = value;
OnPropertyChanged();
}
}
#endregion
}
XAML:
<HelpButton x:Name="HB" TopicName="{Binding
Source={x:Static local:ViewModels.HelpViewModel},
Path=HelpTopic}" />
This way anyone can change ViewModels.HelpViewModel.HelpTopic
, from anywhere, without needing access to the HelpButton
instance.
Just note even if you're not following a strict MVVM pattern (you may or may not be), binding to a backing view model here to serve as the common state is gonna be much easier than trying to have controls directly manipulate each others' properties.