在ResourceDictionary中的DataTemplate的代码后端

4
我正在尝试使用代码后台来支持DataTemplate中的事件处理程序。以下代码在作为窗口的代码后台时运行良好,但在作为ResourceDictionary的代码后台时无法编译。我知道使用Commands是更好的选择,但这主要是为了测试资源字典中资源的事件处理,以便更好地组织我的代码。我的目标是更好地组织我的代码,但这并不是我认为分离的ResourceDictionary文件应该提供的简单的“包含”行为。
在MainWindow.xaml中:
    <Window x:Class="Wizbang.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:my="clr-namespace:DevComponents.WpfEditors;assembly=DevComponents.WpfEditors"
        xmlns:diag="clr-namespace:System.Diagnostics;assembly=WindowsBase"
        xmlns:local ="clr-namespace:Wizbang"
        xmlns:m ="clr-namespace:Wizbang.Model"
        xmlns:vm="clr-namespace:Wizbang.ViewModel"
        xmlns:vw="clr-namespace:Wizbang.View"
        DataContext="{Binding Path=Main, Source={StaticResource Locator}}"
        Title="Wizbang" Height="760" Width="1335" WindowStartupLocation="CenterScreen">

        <Window.Resources>
            <ResourceDictionary>
                 <ResourceDictionary Source="Resources/MainWindowResources.xaml" />
            </ResourceDictionary>
        </Window.Resources>

在MainWindow.xaml.cs和MainWindowResources.xaml.cs的代码后台中,相同的代码:
private void btnSave_Click(object sender, RoutedEventArgs e)
        {
            //switch item template
            Button btn = (Button)sender;
            //command contains the list item
            ContentControl itm = (ContentControl)btn.CommandParameter;

            itm.SetValue(ContentTemplateProperty, this.FindResource("DetailedTemplate") as DataTemplate);

            //this.UpdateLayout();

        }

当我将ResourceDictionary内联到MainWindow.xaml中,并将代码放在MainWindow.xaml.cs中时,一切正常。但是,当我尝试使用单独的文件作为ResourceDictionary时,代码无法编译。编译器抱怨最后一行:

itm.SetValue(ContentTemplateProperty, this.FindResource("DetailedTemplate") as DataTemplate);

this.FindResource()不是一个有效的方法,且"ContentTemplateProperty"未找到:
错误4 'ContentTemplateProperty'在当前上下文中不存在 C:...\Visual Studio 2010\Projects\Wizbang\Wizbang\Resources\MainWindowResources.xaml.cs 36 26 Wizbang
错误5 'Wizbang.Resources.MainWindowResources'不包含定义为'FindResource'的内容,也没有接受类型为'Wizbang.Resources.MainWindowResources'的第一个参数的扩展方法'FindResource' (是否缺少使用指令或程序集引用?) C:...\Visual Studio 2010\Projects\Wizbang\Wizbang\Resources\MainWindowResources.xaml.cs 36 56 Wizbang
如果我删除最后一行,则代码编译和运行,但按钮没有功能。 我认为我的问题是从ResourceDictionary的角度映射最后一行的引用,但我不确定为什么它应该有所不同。
感谢您的任何想法。
比尔

这与MVVM有什么关系?看到[mvvm]和[codebehind]标签一起出现,让我感到很不舒服。 - user1228
@Will:即使Erno在下面提出了处理ViewModel中的RoutedEvents的绝妙建议,我仍然觉得有可能需要在代码后台处理一些常规事件——即使它是某种事件到命令的代码。我的研究似乎表明,偶尔在代码后台处理事件仍然是必要的,以避免复杂的替代方案。因此,与MVVM的联系在于能够处理包含在ResourceDictionary中的DataTemplate的事件,并且如果需要,能够将事件信息推送到ViewModel中的一个命令。 - Bill
2个回答

3
这是因为代码不再在窗口类中。您需要重新查找它(或想要放置模板的任何控件)。
Window parentWindow = Window.GetWindow(btn);
itm.SetValue(Window.ContentTemplateProperty, parentWindow.FindResource("DetailedTemplate") as DataTemplate);

谢谢!我知道我漏掉了一些基础的东西。这是实际修复它的代码:Window parentWindow = Window.GetWindow(btn); itm.SetValue(Window.ContentTemplateProperty, parentWindow.FindResource("DetailedTemplate") as DataTemplate); - Bill
啊,是的...我不太确定确切的答案。我会更新答案的。谢谢。 - aqwert

3

我认为使用命令(Command)会更加简洁明了。


感谢您的评论。我理解某些控件(其中包括按钮)具有Command机制的可用性,也许正因为按钮具有命令可用性,所以它不是一个好的例子。然而,正如我在描述中提到的那样,这种情况主要是一种测试,考虑到需要支持其他事件——甚至是使用事件到命令机制——其中命令不可用或不合适。 - Bill
@Bill:我明白。在这种情况下,请考虑使用Blend SDK中的Behaviors,以便将任意事件绑定到命令:http://kishordaher.wordpress.com/2009/07/18/routedevent-to-command-action-behavior-blend-3/ - Emond
非常好。再次感谢您。对于试图遵循MVVM范例的开发人员,这确实填补了事件和命令之间的差距。请问您是否知道这是仅限于.NET 4的功能,还是可以在.NET 3.5中使用? - Bill
它也适用于.NET 3.5。请在此处查看:http://www.microsoft.com/downloads/en/details.aspx?FamilyID=f1ae9a30-4928-411d-970b-e682ab179e17&displaylang=en 还有一个适用于Silverlight 4的版本,需要.NET 4。 - Emond

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接