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

时间:2020-03-06 14:21:05  来源:igfitidea点击:

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

解决方案

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

我想我们要问的是我们想要ResourceDictionary的代码隐藏文件。我们完全可以做到这一点!实际上,我们可以使用与Window相同的方法来执行此操作:

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

<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的文件后面创建代码:

namespace MyCompany.MyProject
{
    partial class MyResourceDictionary : ResourceDictionary
    { 
       public MyResourceDictionary()
       {
          InitializeComponent();
       }     
       ... // event handlers ahead..
    }
}

这样就完成了。我们可以将任何所需的代码放在后面:方法,属性和事件处理程序。

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

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

<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元素:

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

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

Gishu虽然这似乎是"通常不鼓励实践",但我们可能想要这样做的原因之一是:

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

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

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