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

Cri*_*ade 147 wpf

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

age*_*ped 206

我想你要问的是你想要一个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">
Run Code Online (Sandbox Code Playgroud)

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

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

而且你已经完成了.您可以在代码中放置您想要的任何内容:方法,属性和事件处理程序.

== 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>
Run Code Online (Sandbox Code Playgroud)

  • 确保在partial class codebehind中提供默认构造函数,并确保它调用InitializeComponent().(就我而言,我使用MEF导出资源字典.) (29认同)
  • 您还必须将ResourceDictionary的XAML文件上的Build Action设置为"Page",否则InitializeComponent()调用将无法编译.(默认情况下,ResourceDictionary XAML文件通常设置为"Resource".) (8认同)
  • 作为ageektrapped答案的补充说明:确保将代码隐藏类的完全限定名称放在x:Class属性中.`x:Class ="MyCompany.MyProject.MySubFolder1.MyResourceDictionary"`否则,如果你只是把x:Class ="MyResourceDictionary",那么xaml解析器将找不到你的类. (7认同)
  • 更新了upvoted评论的代码段.我觉得有必要完成答案; 一个常见的错误.我刚刚做到了:)如果你不喜欢它还原.谢谢你的回答. (4认同)
  • 请注意(至少在wp8.1中)这不再有效,您必须创建资源二进制引用的自定义用户控件 (2认同)

Pho*_*bis 9

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

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

Button myButton = this.GetTemplateChild("ButtonName") as Button;
if(myButton != null){
   ...
}
Run Code Online (Sandbox Code Playgroud)

如果要在自定义控件加载时连接到控件,可以在OnApplyTemplate方法中执行操作.需要重写OnApplyTemplate才能执行此操作.这是一种常见做法,允许您的风格与控件保持断开状态.(样式不应该依赖于控件,但控件应该取决于具有样式).

  • Phobis我认为将Dictionary与页面分离的目的是关于主页面xaml的可重用性和可读性.上述解决方案也适用于我. (7认同)

小智 5

Gishu - 虽然这似乎是"一般不被鼓励的练习"这是你可能想要这样做的一个原因:

文本框获得焦点时的标准行为是将插入符号放置在控件失去焦点时的相同位置.如果您希望在整个应用程序中,当用户选中任何文本框时,文本框的整个内容都会突出显示,那么在资源字典中添加一个简单的处理程序就可以了.

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

完全同意任何特定于应用程序功能的东西不应该在资源字典后面的代码中.