1

I have data templates defined in some ResourceDictionary:

<DataTemplate DataType="{x:Type local:SomeType}">
    <TextBlock Text="{Binding Text}" />
</DataTemplate>

I need to get instance of created view (e.g. to attach ToolTip dynamically or control Visibility).

I can subscribe to Loaded event, but I'd like more xaml approach to this, because data templates can be redefined and repeating code-behind is tedious.

Pseudo-code:

<TextBlock This="{Binding View}" />

How can I achieve this?


I tried to create attached behavior to use it like this

<TextBlock local:MyBehavior.View="{Binding View}" />

but shamefully fail :(

public class MyBehavior
{
    public static BindingBase GetView(DependencyObject obj) => (BindingBase)obj.GetValue(ViewProperty);
    public static void SetView(DependencyObject obj, BindingBase value) => obj.SetValue(ViewProperty, value);
    public static readonly DependencyProperty ViewProperty =
        DependencyProperty.RegisterAttached("View", typeof(BindingBase), typeof(MyBehavior), new PropertyMetadata(null, (d, e) =>
        {
            var element = d as FrameworkElement;
            if (element == null)
                throw new ArgumentException("Only used with FrameworkElement");
            element.Loaded += (s, a) => GetView(element). ???; // kek
        }));
}
Community
  • 1
  • 1
Sinatr
  • 20,892
  • 15
  • 90
  • 319
  • Why do you need to get a View? If you what to make a 'dynamic' tooltip, just setup `ControlPresenter` at ... and define this datatemplate for it. – Shakra Jan 12 '17 at 11:52
  • @Shakra, `ToolTip` was just an example as well as this simplified template. Take a look at my attempt, it's only missing the part of how to update source of [`BindingBase`](https://msdn.microsoft.com/en-us/library/system.windows.data.bindingbase(v=vs.110).aspx) (if that make sense, because it doesn't have `Source`?) to have `View` property containing instance of the `TextBlock`. Fixing that is what I'd be happy with. Or maybe there is another (simpler?) way to achieve that, therefore question is about original problem, not attempted solution. – Sinatr Jan 12 '17 at 12:21
  • 1
    The more often i read your question, the more confused i get. In your Example, the `TextBox` **IS** the view of your `local:SomeType`. Therefore you have to tell either your ViewModel whats its view (which is breaking the MVVM-Pattern) or put all your infos in the ViewModel and do the default-MVVM-stuff – lokusking Jan 12 '17 at 12:44
  • @Sinatr it was told befor, it's VERY hard to understand what do you what to do and why do you need a view. As @lokusking told it's a MVVM crush if you'll get a view at viewmodel, so we want to understand why do you need this view, to give some suggestions how it can be done in other way. (my another guest about you purposes: if you want to reuse some `DataTemplate` in OOP style you can read [this](http://stackoverflow.com/questions/22643857/sharing-a-part-of-datatemplate-in-a-resource-dictionary-wpf) question as an example) – Shakra Jan 12 '17 at 13:13
  • @lokusking, I understand that having view instance in the viewmodel is bad, still you will often find that e.g. when using `PasswordBox`. Same here, I have my reasons behind, trust me. Is it not clear what I want? Is it possible to achieve? – Sinatr Jan 12 '17 at 13:22
  • I think @shakra and me both can imagine **what** you want, but no solid reason **why** you want it. `PasswordBox` is more an exception than the default in WPF. It is designed like this because of securityreasons as you might imagine. DataTemplates seem to me the wrong way to go to achieve what ever you want. They are made for telling the ViewModel how it should be displayed, not the other way round. DataTemplates template your data! Not more, not less. – lokusking Jan 12 '17 at 13:32
  • @Sinatr if you need view you can get your `DataTemplate` via [FindResource] ( https://msdn.microsoft.com/ru-ru/library/system.windows.frameworkelement.findresource(v=vs.110).aspx ) and then you can get a root element by using `LoadContent()` method of `DataTemplate` – Shakra Jan 12 '17 at 13:35
  • @Sinatr You can get PasswordBox without breaking the MVVM pattern and very easily. Every problem which requires some control property (which cannot be binded) is achievable. Other than that... You can use this question and answer to globally solve your problem. http://stackoverflow.com/questions/10027182/how-to-set-an-evenhandler-in-wpf-to-all-windows-entire-application – shahar eldad Jan 12 '17 at 15:40

0 Answers0