绑定/引用方法到XAML WPF

ddhy6vgd  于 2022-12-20  发布在  其他
关注(0)|答案(3)|浏览(188)

我有这个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>

我的C#代码:

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

问题是,我得到以下错误:

**错误1

“ResourceDictionary”根元素需要x:Class特性才能支持XAML文件中的事件处理程序。请移除MouseEnter事件的事件处理程序,或向根元素添加x:Class特性。**

brqmpdu1

brqmpdu11#

你可以通过将代码附加到你的ResourceDictionary来实现。实现这一点的几个简单步骤是:

  • 假设ResourceDictionary文件名为CustomResources.xaml。在同一目录中添加另一个文件,名称为CustomResources.xaml.cs。创建继承自ResourceDictionary的partial class CustomResources

声明MouseEnter的处理程序,隐藏代码就准备就绪了。

using System;
using System.Windows;
namespace WpfApplication1
{
    public partial class CustomResources : ResourceDictionary
    {
        public void MouseEnter(object sender, EventArgs e)
        {
            MessageBox.Show("Test");
        }
    }
}
  • 现在,在XAML中设置x:Class属性并将处理程序设置为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>
iq0todco

iq0todco2#

您需要添加x:class属性并指定资源所在的位置,以及事件处理程序所在的位置,请参阅Is it possible to set code behind a resource dictionary in WPF for event handling?以了解这方面的示例。

yhxst69z

yhxst69z3#

问题是Template需要知道它所应用的对象是否有MouseEnter,不幸的是,即使将您的x:Type应用到模板,xaml编译器也没有足够的资源继续运行。
我以前做过类似的事情,让ResourceDictionary识别我正在模板化的属性,看起来我用了一种样式来解决它。完整代码在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>

但是你想通过{StaticResource ...}把你的句柄绑定到你的objectDataPresenter上的一个方法,我不确定你能不能做到。相反,你可能更好地使用一个普通的绑定{Binding Path=...}绑定到DataContext上,我认为你仍然可以通过{StaticResource.. }提供DataContext

相关问题