views:

564

answers:

3

Hi,

I was wondering if in WPF you are able to get the actual instances of the datatemplate objects. For example in the following situation:

<UserControl>
    <UserControl.Resources>
        <DataTemplate x:Key="MyTemplate">
            <CustomControl ></CustomControl>
        </DataTemplate>
    </UserControl.Resources>

    <ListBox DataTemplate="{StaticResource MyTemplate}"></ListBox>
</UserControl>

Assume that CustomControl has a CustomEvent and a public CustomMethod. I want to access that event and the public method in the user control. Is this possible? How would I be able to do this? Thanks in advance for any help.

Cheers,

Nilu

A: 

You can create an object which attaches to the CustomControl and interacts with it.

This blogpost here illustrated some useful concepts that we can expand upon: ICommand for Silverlight with Attached Behaviors

So instead of attaching to the click event of a button (which in WPF already has a command anyways) you can create a class which attaches to your custom control.

Following the pattern in the referenced blog post you would end up with:

<CustomControl 
  MyNamespace:CustomControlCommand.EventCommand=
  "{Binding Path=CommandHandler}" />

This would give you access to the events of the CustomControl by turning them into commands.

Doug Ferguson
+1  A: 

You need to find the ContentPresenter holding the ListBox (by navigating the VisualTree) and then use

myDataTemplate.FindName("myCustomControl", myListBox);

There is an example on MSDN: http://msdn.microsoft.com/en-us/library/bb613579.aspx.

hwiechers
Going via the VisualTree as most often not what you want and better solutions exist for this case
Pieter Breed
I answered the question "[how to] get the actual instances of the datatemplate objects." The question heading is "Access items inside the DataTemplate in WPF", after all. As far as I can see, this is the standard way to doing it.
hwiechers
Voting this answer up, as it was the answer I was looking for when I found this question. It may not be the best way, and it is fine to offer alternatives, but that's no reason to down-vote what is clearly the correct answer to the question being asked.
Niall
+1 for the example link
Alex Marshall
A: 

I don't see the ItemsSource databinding on the ListBox, so I'm assuming you left it out. If you bind to something like an ObservableCollection<> then each item in the ListBox will have it's own ViewModel class. You may have public methods on those as much as you like.

If you want an event in the custom control to be handled, handle it in code-behind in the lowest level you can, in this case in the code-behind of the UserControl.

Then, in each ViewModel have an ICommand instance (or a routed command if that suits your purpose). In the UserControl you have a DataContext which you can cast to the type of your ViewModel. So the event handler can access the ViewModel and execute Commands.

Here is Josh Smith's article on Routed Commands which you might find interesting

In this article on Apps with MVVM architecture, Josh described custom ICommands

(This is pseudo-code)

class ViewModelType {
    public void DoSomething() { /* ... */ }
    public ICommand DoSomethingCommand { get; set; }
    public string Property { get; set; }
}

class CodeMehind {
    public void EventHandler(object, args) {
        (DataContext as ViewModelType).DoSomethingElseCommand.Execute();
    }
}
Pieter Breed