简体   繁体   中英

Binding/Referencing Method to XAML WPF

I have this xaml

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:l="clr-namespace:My.Windows"
                    >
    <ObjectDataProvider x:Key="TitledWindow_Test" MethodName="Test" ObjectInstance={x:Type l:TitledWindow}">
    <ControlTemplate x:Key="TitledWindowControlTemplateKey" x:Name="PART_ControlTemplate" TargetType="{x:Type l:TitledWindow}"
        <Rectangle>
            <Rectangle.Style>
                <EventSetter Event="Mouse.MouseEnter" Handler="{StaticResource TitledWindow_Test}">
            </Rectangle.Style>
        </Rectangle>
    </ControlTemplate>
</ResourceDictionary>

And my c# code:

namespace My.Windows
{
    public partial class TitledWindow : Window
    {
        public void Test()
        {
            MessageBox.Show("Test");
        }
    }
}

The problem is that i get the following error:

Error 1
'ResourceDictionary' root element requires ax:Class attribute to support event handlers in the XAML file. Either remove the event handler for the MouseEnter event, or add ax:Class attribute to the root element.

Well you can do that by attaching code behind to your ResourceDictionary . Few simple steps to achieve that are:

  • Say ResourceDictionary file name is CustomResources.xaml . Add another file in same directory besides your ResourceDictionary with name CustomResources.xaml.cs . Create partial class CustomResources inheriting from ResourceDictionary.

Declare your handler for MouseEnter and code behind is ready.

using System;
using System.Windows;
namespace WpfApplication1
{
    public partial class CustomResources : ResourceDictionary
    {
        public void MouseEnter(object sender, EventArgs e)
        {
            MessageBox.Show("Test");
        }
    }
}
  • Now, in XAML set x:Class attribute and set handler to MouseEnter .

XAML :

<ResourceDictionary
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             x:Class="WpfApplication1.CustomResources"
             xmlns:local="clr-namespace:WpfApplication1">
    <ControlTemplate x:Key="TitledWindowControlTemplateKey" 
                     x:Name="PART_ControlTemplate"
                     TargetType="{x:Type local:TitleWindow}">
        <Rectangle>
            <Rectangle.Style>
                <Style TargetType="Rectangle">
                    <EventSetter Event="Mouse.MouseEnter" Handler="MouseEnter"/>
                </Style>
            </Rectangle.Style>
        </Rectangle>
    </ControlTemplate>    
</ResourceDictionary>

The problem is that the Template needs to know if what it is being applied to has a MouseEnter . Unfortunately even by applying your x:Type to the template, the xaml compiler doesn't have enough to go on.

I have done something similar before in getting the ResourceDictionary to recognise the porepoties of what I'm templating to and it looks like I used a style to get around it. Full code in http://winchrome.codeplex.com/SourceControl/latest#WinChrome/UI/VS2012ResourceDictionary.xaml .

<ResourceDictionary ... >

<Style x:Key="CloseButtonStyle" TargetType="{x:Type Button}" >
  ...
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Button}">
                <Border x:Name="bd" ....>
                ....
                </Border>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsMouseOver" Value="True" SourceName="bd">
                        <Setter Property="Background" TargetName="bd" Value="{DynamicResource {x:Static SystemColors.ControlLightLightBrushKey}}"/>
                        ... 
                    </Trigger>
                    <Trigger Property="IsPressed" Value="True">
                        <Setter Property="Background" TargetName="bd">
                          ...
                        </Setter>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

However you want to then bind your handler to a method on your objectDataPresenter via a {StaticResource ...} which I'm not sure that you can. Instead you might be better to instead bind onto the DataContext using a normal binding {Binding Path=...} , I think you might still be able to provide the DataContext via the {StaticResource.. } .

You need to add the x:class attribute and specify where the resource is, and where the event handler would be located. See Is it possible to set code behind a resource dictionary in WPF for event handling? for an example of this.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM