Click here to Skip to main content
15,917,455 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
Hi all,

I have a DataGrid where I apply the ColumnHeaderStyle. The style in turn contains template that contains a button.
When user click on the button I want to be able to catch it at the window level (above the DataGrid).

When using "regular" command (ButtonBase.Click) it works, but when I'm using blend it doesn't.

Please help.
XML
<Window x:Class="Tac.MainWindow"
          xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
             xmlns:tac="clr-namespace:Tac"
             mc:Ignorable="d"
             d:DesignHeight="300" d:DesignWidth="300" ButtonBase.Click="dataGrid1_Click">

    <!--This won't fire. But ButtonBase.Click works just fine !?-->
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="Click">
            <tac:ExecuteCommandAction Command="{Binding FilterLoadedCommand}"/>
        </i:EventTrigger>
    </i:Interaction.Triggers>

    <Window.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="Generic.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Window.Resources>

    <DataGrid x:Name="dataGrid1" IsReadOnly="True" SelectionMode="Extended"
            ColumnHeaderStyle="{StaticResource DataGridHeaderFilterControl}"
            ItemsSource="{Binding ItemsSource, Mode=OneWay}">

    </DataGrid>
</Window>

C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Data;
using System.Collections;

namespace Tac
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        DataTable dt = new DataTable();

        public RelayCommand<object> FilterLoadedCommand { get; private set; }

        public MainWindow()
        {
            InitializeComponent();

            FilterLoadedCommand = new RelayCommand<object>(param => FilterLoadedChanged());

            DataContext = this;

            dt.Columns.Add("Vendor", typeof(string));

            for (int i = 0; i < 20; i++)
            {
                dt.Rows.Add(Convert.ToChar(i + 65));
            }

            this.dataGrid1.ItemsSource = new DataView(dt);
        }

        // Never arrives here !!
        void FilterLoadedChanged()
        {

        }

        // This works
        private void dataGrid1_Click(object sender, RoutedEventArgs e)
        {

        }
    }
}

XML
<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:theme="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero"
    xmlns:s="clr-namespace:System;assembly=mscorlib"
    xmlns:filter="clr-namespace:FilterLibrary.Filter"
    xmlns:local="clr-namespace:FilterLibrary">

    <Style x:Key="DataGridHeaderFilterControl" TargetType="{x:Type DataGridColumnHeader}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type DataGridColumnHeader}">
                    <Button Height="25" Content="Click"/>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>
Posted
Updated 12-Dec-10 23:13pm
v3

1 solution

After a lot of investigation I have found the following.
If event is fired from the control located in the Window.Resources
it won't be caught by the blend no matter what.
The only option to make it work is to register this event in the MainWindow.cs .

Here is the code. The event is never fired if clicked on the button

<pre lang="xml"><Window x:Class="Tac.MainWindow"
          xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
             xmlns:tac="clr-namespace:Tac"
             mc:Ignorable="d"
             d:DesignHeight="300" d:DesignWidth="300" >

    <i:Interaction.Triggers>
        <!--This never works no matter what-->
        <i:EventTrigger EventName="FilterLoaded" SourceName="MyBtn">
            <tac:ExecuteCommandAction Command="{Binding FilterLoadedCommand}"/>
        </i:EventTrigger>
    </i:Interaction.Triggers>

    <Window.Resources>
        <Style x:Key="DataGridHeaderFilterControl" TargetType="{x:Type DataGridColumnHeader}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type DataGridColumnHeader}">
                        <tac:MyButton Height="25" Content="Click" x:Name="MyBtn"/>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Window.Resources>

    <DataGrid x:Name="dataGrid1" IsReadOnly="True" SelectionMode="Extended"
            ColumnHeaderStyle="{StaticResource DataGridHeaderFilterControl}"
            ItemsSource="{Binding ItemsSource, Mode=OneWay}">
    </DataGrid>
</Window>



using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Data;
using System.Collections;
namespace Tac
{
   
    public partial class MainWindow : Window
    {
        DataTable dt = new DataTable();
        public RelayCommand<object> FilterLoadedCommand { get; private set; }
        public MainWindow()
        {
            InitializeComponent();
            FilterLoadedCommand = new RelayCommand<object>(param => FilterLoadedChanged());
            DataContext = this;
            dt.Columns.Add("Vendor", typeof(string));
            for (int i = 0; i < 5; i++)
            {
                dt.Rows.Add(Convert.ToChar(i + 65));
            }
            this.dataGrid1.ItemsSource = new DataView(dt);
        }
        // Never arrives here if the event is fired from the template !!
        void FilterLoadedChanged()
        {
        }
    }
}


<pre lang="cs">using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using System.Windows;
using System.Collections;

namespace Tac
{
    class MyButton : Button
    {
        public static readonly RoutedEvent FilterLoadedEvent = EventManager.RegisterRoutedEvent(
          "FilterLoaded", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(MyButton));

        public event RoutedEventHandler FilterLoaded
        {
            add { AddHandler(FilterLoadedEvent, value); }
            remove { RemoveHandler(FilterLoadedEvent, value); }
        }

        protected override void OnClick()
        {
            base.OnClick();

            RaiseEvent(new RoutedEventArgs(MyButton.FilterLoadedEvent));
        }
    }
}



Now if I would add the following code in the MainWindow

<pre lang="cs">public static readonly RoutedEvent FilterLoadedEvent = EventManager.RegisterRoutedEvent(
         "FilterLoaded", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(MainWindow));

       public event RoutedEventHandler FilterLoaded
       {
           add { AddHandler(FilterLoadedEvent, value); }
           remove { RemoveHandler(FilterLoadedEvent, value); }
       }



And fire the event from the MyButton as:
RaiseEvent(new RoutedEventArgs(MainWindow.FilterLoadedEvent));

it would all work fine.

Any idea how to fix it?

Thank you
 
Share this answer
 
v2

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900