是否可以在WPF中的资源字典后面设置代码以进行事件处理?

是否可以在WPF中的资源字典后面设置代码以进行事件处理?

Is it possible to set code behind a resource dictionary in WPF for event handling?

是否可以在WPF中的资源字典后面设置代码。 例如,在按钮的用户控件中,您可以在XAML中声明它。 按钮单击的事件处理代码在控件后面的代码文件中完成。 如果要使用按钮创建数据模板,那么如何在资源字典中单击按钮来编写事件处理程序代码。


我想您要问的是您想要ResourceDictionary的代码隐藏文件。您完全可以做到这一点!实际上,您的操作方式与窗口相同:

假设您有一个称为MyResourceDictionary的ResourceDictionary。在MyResourceDictionary.xaml文件中,将x:Class属性放在根元素中,如下所示:

1
2
3
4
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    x:Class="MyCompany.MyProject.MyResourceDictionary"
                    x:ClassModifier="public">

然后,使用以下声明在名为MyResourceDictionary.xaml.cs的文件后面创建代码:

1
2
3
4
5
6
7
8
9
10
11
namespace MyCompany.MyProject
{
    partial class MyResourceDictionary : ResourceDictionary
    {
       public MyResourceDictionary()
       {
          InitializeComponent();
       }    
       ... // event handlers ahead..
    }
}

这样就完成了。您可以在代码中放置任何所需内容:方法,属性和事件处理程序。

== Windows 10应用程序的更新==

万一您正在使用UWP,还需要注意一件事:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<Application x:Class="SampleProject.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:rd="using:MyCompany.MyProject">
<!-- no need in x:ClassModifier="public" in the header above -->

    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>

                <!-- This will NOT work -->
                <!-- <ResourceDictionary Source="/MyResourceDictionary.xaml" />-->

                <!-- Create instance of your custom dictionary instead of the above source reference -->
                <rd:MyResourceDictionary />

            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>

</Application>

我不同意"苦恼"……使用部分类的方法不是一个好习惯。那么,将词典与页面分开的目的是什么?

在隐藏的代码中,您可以使用以下命令访问x:Name元素:

1
2
3
4
Button myButton = this.GetTemplateChild("ButtonName") as Button;
if(myButton != null){
   ...
}

如果要在加载自定义控件时连接到控件,可以在OnApplyTemplate方法中执行此操作。为此,需要重写OnApplyTemplate。这是一种常见的做法,可以使您的样式与控件保持断开连接。 (样式不应取决于控件,但控件应取决于具有样式)。


Gishu-尽管这似乎是"通常不鼓励实践",但您可能想要这样做的原因之一是:

文本框获得焦点时的标准行为是将插入符号放置在控件失去焦点时的位置。如果您希望在整个应用程序中都希望当用户使用Tab键选择任何文本框时,突出显示该文本框的全部内容,则可以在资源字典中添加一个简单的处理程序来解决问题。

您希望默认用户交互行为与开箱即用行为不同的任何其他原因,似乎都是资源字典中隐藏代码的良好候选者。

完全同意,任何特定于应用程序功能的内容都不应放在资源字典后面的代码中。


XAML用于构造不包含代码的对象图。
数据模板用于指示如何在屏幕上呈现自定义用户对象……(例如,如果它是一个列表框项目)行为不属于数据模板的专业领域。重新绘制解决方案...


推荐阅读