Passing element (XamGrid) as parameter in Message.Attach

Jan 18, 2011 at 10:59 AM


I need to pass whole FrameworkElement (in my cas XamGrid) as an action parameter.

This is my xaml (simplified):

           <ig:XamGrid x:Name="XamGrid" ... />
            <Button Content="Export..." cal:Message.Attach="ExportToExcel(XamGrid)" >


and the method in ViewModel is obviously

        public void ExportToExcel(XamGrid xamGrid)
        { ... }

When clicked the button, the method is called, however the parameter is null. I found out that happens because there are no conventions for XamGrid, and convetion for base class is used instead. That is System.Windows.Control, and it's conventional property to bind is DataContextProperty. That of course fails to bind to the parameter.

Is there any simple solution? I tried to create some custom conventions, but the trouble is quite deep - conventions can only bind to properties. Since I don't need to bind to property, but I need to pass whole UI element, I'm stuck.

I find it a little weird, that when no convention is found, CM ends up with unsuccesful attempt to bind to DataContext (also without notification). I would expect allowing to pass the UI element as parameter - which seems impossible (please don't feel this in a bad way, I like CM a lot a I do appreciate all the work done!)

I found one solution, but it's quite a lot of code and I don't like that much:

            <Button Content="Export..." cal:Message.Attach="ExportToExcel(XamGrid)" >
                    <i:EventTrigger EventName="Click">
                        <cal:ActionMessage MethodName="ExportToExcel">
                            <cal:Parameter Value="{Binding ElementName=XamGrid}" />

Jan 18, 2011 at 1:51 PM

Well, usually it's not a good practice to pass controls to a VM. I understand your situation though. Unfortunately, there is not a syntax via Message.Attach to do what you want. As you discovered it is possible using the explicit trigger syntax. That's probably the best way to go. Another option would be to create a custom Trigger that passes the control as the invocation parameter rather than the event args. A third option would be to create an IResult, which through the ActionExecutionContext, has access to the view and can obtain any control that is needed.

Jan 18, 2011 at 3:33 PM

Hi, thank you for response and interesting suggestions. I agree that passing UI controls is not a good practice and also is not even a common usecase.

Since I have lots of viewmodels that should support exporting to excel, I decided to go with this solution:

Create custom button (ExportButton) that gets reference to XamGrid to be exported. This has the disadvantage of not talking to ViewModel at all, so the behaviour will be hard to modify (everyone now export in the same manner). On the other hand, I need extremely short code to solve the issue.

This is the ExportButton class:

    public class ExportButton : Button
        public static readonly DependencyProperty XamGridProperty
            = DependencyProperty.Register("XamGrid", typeof(XamGrid), typeof(ExportButton), null);

        public XamGrid XamGrid
            get { return (XamGrid)GetValue(XamGridProperty); }
            set { SetValue(XamGridProperty, value); }

        public ExportButton()
            this.Click += new RoutedEventHandler(ExportButtonClick);
            this.Content = "Export";

        private void ExportButtonClick(object sender, RoutedEventArgs e)
            var xamGrid = this.XamGrid;
            if (xamGrid == null) throw new NullReferenceException("No grid bound to this button.");


and this is how XAML looks like now:

            <ig:XamGrid x:Name="XamGrid"

            <Exports:ExportButton XamGrid="{Binding ElementName=XamGrid}"/>

It has limitations and I may be forced to change the solution, but it works so far and it's the shortest XAML I could make. I am thinking of changing the ExportButton for attached property at button, so that I can use standard controls. If anyone is interested more in this issue, I will gladly discuss possible solutions.